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;
|
fFUSEConfig = *config;
|
||||||
|
|
||||||
// do the initialization
|
// 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
|
// notify the mount thread
|
||||||
PRINT((" notifying mount thread\n"));
|
PRINT((" notifying mount thread\n"));
|
||||||
fInitStatus = error;
|
|
||||||
delete_sem(fInitSemaphore);
|
delete_sem(fInitSemaphore);
|
||||||
|
|
||||||
// loop until unmounting
|
// loop until unmounting
|
||||||
@ -287,10 +295,10 @@ PRINT((" waiting for unmounting done\n"));
|
|||||||
|
|
||||||
fExitSemaphore = -1;
|
fExitSemaphore = -1;
|
||||||
|
|
||||||
if (error == B_OK)
|
if (fFS != NULL)
|
||||||
fuse_fs_destroy(fFS);
|
fuse_fs_destroy(fFS);
|
||||||
|
|
||||||
return error;
|
return fExitStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
status_t FinishInitClientFS(fuse_config* config,
|
status_t FinishInitClientFS(fuse_config* config,
|
||||||
const fuse_operations* ops, size_t opSize,
|
const fuse_operations* ops, size_t opSize,
|
||||||
void* userData);
|
void* userData);
|
||||||
|
status_t MainLoop(bool multithreaded);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ArgumentVector;
|
class ArgumentVector;
|
||||||
|
@ -10,7 +10,30 @@
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
KEY_KERN_FLAG,
|
||||||
|
KEY_KERN_OPT,
|
||||||
|
KEY_FUSERMOUNT_OPT,
|
||||||
|
KEY_SUBTYPE_OPT,
|
||||||
|
KEY_MTAB_OPT,
|
||||||
|
KEY_ALLOW_ROOT,
|
||||||
|
KEY_RO,
|
||||||
KEY_HELP,
|
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 }
|
#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
|
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
|
static int
|
||||||
fuse_lib_opt_proc(void *data, const char *arg, int key,
|
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
|
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;
|
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) ||*/
|
return /*fuse_lowlevel_is_lib_option(opt) ||*/
|
||||||
fuse_opt_match(fuse_lib_opts, 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" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
#include "fuse_api.h"
|
#include "fuse_api.h"
|
||||||
#include "fuse_config.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,
|
printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, opSize,
|
||||||
userData);
|
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);
|
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||||
|
|
||||||
fuse_config config;
|
int result = 1;
|
||||||
memset(&config, 0, sizeof(config));
|
|
||||||
config.entry_timeout = 1.0;
|
// create the kernel channel
|
||||||
config.attr_timeout = 1.0;
|
struct fuse_chan* channel = fuse_mount("/dummy", &args);
|
||||||
config.negative_timeout = 0.0;
|
if (channel != NULL) {
|
||||||
config.intr_signal = SIGUSR1;
|
// 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);
|
fuse_opt_free_args(&args);
|
||||||
|
|
||||||
if (!success)
|
return result;
|
||||||
return 1;
|
|
||||||
|
|
||||||
// run the main loop
|
|
||||||
status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
|
|
||||||
op, opSize, userData);
|
|
||||||
|
|
||||||
|
|
||||||
return error == B_OK ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -60,3 +67,107 @@ fuse_get_context(void)
|
|||||||
? (fuse_context*)requestThread->GetContext()->GetFSData()
|
? (fuse_context*)requestThread->GetContext()->GetFSData()
|
||||||
: NULL;
|
: 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