Implemented more of the detailed FUSE initialization functions for file systems
that use them directly instead of fuse_main(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30024 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ab15dd259a
commit
861dbb4810
@ -272,11 +272,19 @@ PRINT(("FUSEFileSystem::FinishInitClientFS()\n"));
|
||||
fFUSEConfig = *config;
|
||||
|
||||
// do the initialization
|
||||
status_t error = _InitClientFS(ops, opSize, userData);
|
||||
fInitStatus = _InitClientFS(ops, opSize, userData);
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FUSEFileSystem::MainLoop(bool multithreaded)
|
||||
{
|
||||
// TODO: Respect the multithreaded flag!
|
||||
|
||||
PRINT(("FUSEFileSystem::FinishMounting()\n"));
|
||||
// notify the mount thread
|
||||
PRINT((" notifying mount thread\n"));
|
||||
fInitStatus = error;
|
||||
delete_sem(fInitSemaphore);
|
||||
|
||||
// loop until unmounting
|
||||
@ -287,10 +295,10 @@ PRINT((" waiting for unmounting done\n"));
|
||||
|
||||
fExitSemaphore = -1;
|
||||
|
||||
if (error == B_OK)
|
||||
if (fFS != NULL)
|
||||
fuse_fs_destroy(fFS);
|
||||
|
||||
return error;
|
||||
return fExitStatus;
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
status_t FinishInitClientFS(fuse_config* config,
|
||||
const fuse_operations* ops, size_t opSize,
|
||||
void* userData);
|
||||
status_t MainLoop(bool multithreaded);
|
||||
|
||||
private:
|
||||
class ArgumentVector;
|
||||
|
@ -10,7 +10,30 @@
|
||||
|
||||
|
||||
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 }
|
||||
@ -46,6 +69,48 @@ static const struct fuse_opt fuse_lib_opts[] = {
|
||||
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,
|
||||
@ -61,7 +126,7 @@ fuse_lib_opt_proc(void *data, const char *arg, int key,
|
||||
|
||||
|
||||
int
|
||||
fuse_parse_config_args(struct fuse_args* args, struct fuse_config* config)
|
||||
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;
|
||||
}
|
||||
@ -73,3 +138,104 @@ 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;
|
||||
}
|
||||
|
@ -41,7 +41,10 @@ struct fuse_config {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int fuse_parse_config_args(struct fuse_args* args, struct fuse_config* config);
|
||||
int fuse_parse_lib_config_args(struct fuse_args* args,
|
||||
struct fuse_config* config);
|
||||
|
||||
int fuse_parse_mount_config_args(struct fuse_args* args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -3,8 +3,12 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
#include "fuse_api.h"
|
||||
#include "fuse_config.h"
|
||||
@ -19,29 +23,32 @@ fuse_main_real(int argc, char* argv[], const struct fuse_operations* op,
|
||||
{
|
||||
printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, opSize,
|
||||
userData);
|
||||
// Note: We use the fuse_*() functions here to initialize and run the
|
||||
// file system, although some of them are merely dummies.
|
||||
|
||||
// parse args
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
|
||||
fuse_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.entry_timeout = 1.0;
|
||||
config.attr_timeout = 1.0;
|
||||
config.negative_timeout = 0.0;
|
||||
config.intr_signal = SIGUSR1;
|
||||
int result = 1;
|
||||
|
||||
// create the kernel channel
|
||||
struct fuse_chan* channel = fuse_mount("/dummy", &args);
|
||||
if (channel != NULL) {
|
||||
// create the FUSE handle
|
||||
struct fuse* fuseHandle = fuse_new(channel, &args, op, opSize,
|
||||
userData);
|
||||
if (fuseHandle != NULL) {
|
||||
// run the main loop
|
||||
result = fuse_loop_mt(fuseHandle);
|
||||
|
||||
fuse_destroy(fuseHandle);
|
||||
}
|
||||
|
||||
fuse_unmount("/dummy", channel);
|
||||
}
|
||||
|
||||
bool success = fuse_parse_config_args(&args, &config);
|
||||
fuse_opt_free_args(&args);
|
||||
|
||||
if (!success)
|
||||
return 1;
|
||||
|
||||
// run the main loop
|
||||
status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
|
||||
op, opSize, userData);
|
||||
|
||||
|
||||
return error == B_OK ? 0 : 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -60,3 +67,107 @@ fuse_get_context(void)
|
||||
? (fuse_context*)requestThread->GetContext()->GetFSData()
|
||||
: NULL;
|
||||
}
|
||||
|
||||
|
||||
struct fuse_chan*
|
||||
fuse_mount(const char* mountpoint, struct fuse_args* args)
|
||||
{
|
||||
// make sure the stdin/out/err descriptors are open
|
||||
while (true) {
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ERROR(("fuse_mount(): Failed to open /dev/null: %s\n",
|
||||
strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd > 2) {
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fuse_parse_mount_config_args(args))
|
||||
return NULL;
|
||||
|
||||
return (fuse_chan*)FUSEFileSystem::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fuse_unmount(const char* mountpoint, struct fuse_chan* ch)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
struct fuse*
|
||||
fuse_new(struct fuse_chan* ch, struct fuse_args* args,
|
||||
const struct fuse_operations *op, size_t opSize, void *userData)
|
||||
{
|
||||
// parse args
|
||||
fuse_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.entry_timeout = 1.0;
|
||||
config.attr_timeout = 1.0;
|
||||
config.negative_timeout = 0.0;
|
||||
config.intr_signal = SIGUSR1;
|
||||
|
||||
bool success = fuse_parse_lib_config_args(args, &config);
|
||||
|
||||
if (!success) {
|
||||
PRINT(("fuse_new(): failed to parse arguments!\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// run the main loop
|
||||
status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
|
||||
op, opSize, userData);
|
||||
|
||||
return error == B_OK ? (struct fuse*)FUSEFileSystem::GetInstance() : NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fuse_destroy(struct fuse* f)
|
||||
{
|
||||
// TODO: Implement!
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fuse_loop(struct fuse* f)
|
||||
{
|
||||
status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
|
||||
return error == B_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fuse_loop_mt(struct fuse* f)
|
||||
{
|
||||
status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
|
||||
return error == B_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fuse_exit(struct fuse* f)
|
||||
{
|
||||
// TODO: Implement!
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fuse_interrupted(void)
|
||||
{
|
||||
// TODO: ?
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fuse_invalidate(struct fuse* f, const char* path)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user