genode/repos/libports/src/lib/fuse/fuse.cc

300 lines
5.3 KiB
C++

/*
* \brief libfuse re-implementation
* \author Josef Soentgen
* \date 2013-11-07
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genodes includes */
#include <base/printf.h>
#include <util/string.h>
/* libc includes */
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <fuse.h>
#include <fuse_private.h>
static bool _initialized;
static struct fuse *_fuse;
static struct fuse_context _ctx;
#if 1
#define TRACE PDBG("")
#else
#define TRACE
#endif
struct fuse* Fuse::fuse()
{
if (_fuse == 0) {
PERR("libfuse: struct fuse is zero");
abort();
}
return _fuse;
}
bool Fuse::initialized()
{
return _initialized;
}
extern "C" {
void fuse_genode(const char *s)
{
PLOG("%s: %s", __func__, s);
}
#define FIX_UP_OPERATION1(f, name) \
if(f->op.name == 0) \
f->op.name = dummy_op1;
#define FIX_UP_OPERATION2(f, name) \
if(f->op.name == 0) \
f->op.name = dummy_op2;
static int dummy_op1(void)
{
TRACE;
return -ENOSYS;
}
static int dummy_op2(void)
{
TRACE;
return 0;
}
static int fill_dir(void *dh, const char *name, const struct stat *sbuf, off_t offset)
{
static uint32_t fileno = 1;
struct fuse_dirhandle *dir = (struct fuse_dirhandle*)dh;
if ((dir->offset + sizeof (struct dirent)) > dir->size) {
PWRN("fill_dir buffer full");
return 1;
}
struct dirent *entry = (struct dirent *)(((char*)dir->buf) + dir->offset);
Genode::memset(entry, 0, sizeof (struct dirent));
if (sbuf) {
entry->d_fileno = sbuf->st_ino;
entry->d_type = IFTODT(sbuf->st_mode);
}
else {
entry->d_fileno = fileno++;
entry->d_type = DT_UNKNOWN;
}
/* even in a valid sbuf the inode might by 0 */
if (entry->d_fileno == 0)
entry->d_fileno = fileno++;
size_t namelen = Genode::strlen(name);
if (namelen > 255)
namelen = 255;
Genode::strncpy(entry->d_name, name, namelen + 1);
entry->d_reclen = sizeof (struct dirent);
dir->offset += sizeof (struct dirent);
return 0;
}
/*
* FUSE API
*/
int fuse_version(void)
{
return (FUSE_VERSION);
}
int fuse_main(int argc, char *argv[],
const struct fuse_operations *fsop, void *data)
{
TRACE;
return -1;
}
struct fuse* fuse_new(struct fuse_chan *chan, struct fuse_args *args,
const struct fuse_operations *fsop, size_t size,
void *userdata)
{
TRACE;
_fuse = reinterpret_cast<struct fuse*>(malloc(sizeof (struct fuse)));
if (_fuse == 0) {
PERR("could not create struct fuse");
return 0;
}
_fuse->fc = chan;
_fuse->args = args;
Genode::memcpy(&_fuse->op, fsop, Genode::min(size, sizeof (_fuse->op)));
/**
* Defining a dummy function for each fuse operation is cumbersome.
* So let us faithfully ignore the compiler.
*/
#pragma GCC diagnostic ignored "-fpermissive"
FIX_UP_OPERATION1(_fuse, readlink);
FIX_UP_OPERATION1(_fuse, mknod);
FIX_UP_OPERATION1(_fuse, unlink);
FIX_UP_OPERATION1(_fuse, rmdir);
FIX_UP_OPERATION1(_fuse, symlink);
FIX_UP_OPERATION1(_fuse, rename);
FIX_UP_OPERATION1(_fuse, link);
FIX_UP_OPERATION1(_fuse, chmod);
FIX_UP_OPERATION1(_fuse, chown);
FIX_UP_OPERATION1(_fuse, truncate);
FIX_UP_OPERATION1(_fuse, utime);
FIX_UP_OPERATION2(_fuse, open);
FIX_UP_OPERATION1(_fuse, read);
FIX_UP_OPERATION1(_fuse, write);
FIX_UP_OPERATION1(_fuse, statfs);
FIX_UP_OPERATION1(_fuse, flush);
FIX_UP_OPERATION1(_fuse, release);
FIX_UP_OPERATION1(_fuse, fsync);
FIX_UP_OPERATION1(_fuse, fsyncdir);
FIX_UP_OPERATION1(_fuse, access);
FIX_UP_OPERATION1(_fuse, create);
FIX_UP_OPERATION1(_fuse, utimens);
FIX_UP_OPERATION1(_fuse, read);
FIX_UP_OPERATION1(_fuse, read);
if (_fuse->op.opendir == 0)
_fuse->op.opendir = _fuse->op.open;
if (_fuse->op.releasedir == 0)
_fuse->op.releasedir = _fuse->op.release;
if (_fuse->op.fgetattr == 0)
_fuse->op.fgetattr = _fuse->op.getattr;
if (_fuse->op.ftruncate == 0)
_fuse->op.ftruncate = _fuse->op.truncate;
_fuse->filler = fill_dir;
_fuse->userdata = userdata;
_ctx.fuse = _fuse;
_ctx.uid = 0;
_ctx.gid = 0;
_ctx.pid = 0;
_ctx.private_data = userdata;
_ctx.umask = 022;
_initialized = true;
return _fuse;
}
int fuse_parse_cmdline(struct fuse_args *args, char **mp, int *mt, int *fg)
{
TRACE;
return -1;
}
struct fuse_chan* fuse_mount(const char *dir, struct fuse_args *args)
{
TRACE;
return 0;
}
void fuse_remove_signal_handlers(struct fuse_session *se)
{
TRACE;
}
int fuse_set_signal_handlers(struct fuse_session *se)
{
TRACE;
return -1;
}
struct fuse_session* fuse_get_session(struct fuse *f)
{
TRACE;
return 0;
}
struct fuse_context* fuse_get_context(void)
{
return &_ctx;
}
int fuse_is_lib_option(const char *opt)
{
TRACE;
return -1;
}
int fuse_loop(struct fuse *fuse)
{
TRACE;
return -1;
}
int fuse_loop_mt(struct fuse *fuse)
{
TRACE;
return -1;
}
int fuse_chan_fd(struct fuse_chan *ch)
{
TRACE;
return -1;
}
void fuse_unmount(const char *dir, struct fuse_chan *ch)
{
TRACE;
}
int fuse_daemonize(int foreground)
{
TRACE;
return -1;
}
void fuse_destroy(struct fuse *f)
{
TRACE;
free(f);
}
void fuse_teardown(struct fuse *f, char *mp)
{
TRACE;
}
int fuse_opt_add_arg(struct fuse_args *, const char *)
{
TRACE;
return -1;
}
void fuse_opt_free_args(struct fuse_args *)
{
TRACE;
}
} /* extern "C" */