mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 18:14:24 +08:00
Merged libfuse for OpenIndiana into libfuse-lite
The libfuse used by OpenIndiana has the same features as libfuse-lite though requiring some code variants. Merging them simplifies supporting both. Variants for OpenIndiana are selected when defining __SOLARIS__
This commit is contained in:
parent
3e4c439520
commit
97342d05bc
@ -212,7 +212,7 @@ esac
|
|||||||
|
|
||||||
AC_MSG_CHECKING([fuse compatibility])
|
AC_MSG_CHECKING([fuse compatibility])
|
||||||
case "${target_os}" in
|
case "${target_os}" in
|
||||||
linux*)
|
linux*|solaris*)
|
||||||
AC_ARG_WITH(
|
AC_ARG_WITH(
|
||||||
[fuse],
|
[fuse],
|
||||||
[AS_HELP_STRING([--with-fuse=<internal|external>],[Select FUSE library: internal or external @<:@default=internal@:>@])],
|
[AS_HELP_STRING([--with-fuse=<internal|external>],[Select FUSE library: internal or external @<:@default=internal@:>@])],
|
||||||
@ -220,7 +220,7 @@ linux*)
|
|||||||
[with_fuse="internal"]
|
[with_fuse="internal"]
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
darwin*|netbsd*|solaris*|kfreebsd*-gnu)
|
darwin*|netbsd*|kfreebsd*-gnu)
|
||||||
with_fuse="external"
|
with_fuse="external"
|
||||||
;;
|
;;
|
||||||
freebsd*)
|
freebsd*)
|
||||||
|
@ -624,6 +624,47 @@ void fuse_fs_destroy(struct fuse_fs *fs);
|
|||||||
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
|
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filesystem module
|
||||||
|
*
|
||||||
|
* Filesystem modules are registered with the FUSE_REGISTER_MODULE()
|
||||||
|
* macro.
|
||||||
|
*
|
||||||
|
* If the "-omodules=modname:..." option is present, filesystem
|
||||||
|
* objects are created and pushed onto the stack with the 'factory'
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
struct fuse_module {
|
||||||
|
/**
|
||||||
|
* Name of filesystem
|
||||||
|
*/
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating filesystem objects
|
||||||
|
*
|
||||||
|
* The function may use and remove options from 'args' that belong
|
||||||
|
* to this module.
|
||||||
|
*
|
||||||
|
* For now the 'fs' vector always contains exactly one filesystem.
|
||||||
|
* This is the filesystem which will be below the newly created
|
||||||
|
* filesystem in the stack.
|
||||||
|
*
|
||||||
|
* @param args the command line arguments
|
||||||
|
* @param fs NULL terminated filesystem object vector
|
||||||
|
* @return the new filesystem object
|
||||||
|
*/
|
||||||
|
struct fuse_fs *(*factory)(struct fuse_args *args, struct fuse_fs *fs[]);
|
||||||
|
|
||||||
|
struct fuse_module *next;
|
||||||
|
struct fusemod_so *so;
|
||||||
|
int ctr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
/* ----------------------------------------------------------- *
|
/* ----------------------------------------------------------- *
|
||||||
* Advanced API for event handling, don't worry about this... *
|
* Advanced API for event handling, don't worry about this... *
|
||||||
* ----------------------------------------------------------- */
|
* ----------------------------------------------------------- */
|
||||||
|
@ -32,6 +32,11 @@
|
|||||||
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
||||||
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
|
||||||
|
|
||||||
|
/* This interface uses 64 bit off_t */
|
||||||
|
#if defined(__SOLARIS__) && !defined(__x86_64__) && (_FILE_OFFSET_BITS != 64)
|
||||||
|
#error Please add -D_FILE_OFFSET_BITS=64 to your compile flags!
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -149,6 +154,41 @@ struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args);
|
|||||||
*/
|
*/
|
||||||
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
|
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
/**
|
||||||
|
* Parse common options
|
||||||
|
*
|
||||||
|
* The following options are parsed:
|
||||||
|
*
|
||||||
|
* '-f' foreground
|
||||||
|
* '-d' '-odebug' foreground, but keep the debug option
|
||||||
|
* '-s' single threaded
|
||||||
|
* '-h' '--help' help
|
||||||
|
* '-ho' help without header
|
||||||
|
* '-ofsname=..' file system name, if not present, then set to the program
|
||||||
|
* name
|
||||||
|
*
|
||||||
|
* All parameters may be NULL
|
||||||
|
*
|
||||||
|
* @param args argument vector
|
||||||
|
* @param mountpoint the returned mountpoint, should be freed after use
|
||||||
|
* @param multithreaded set to 1 unless the '-s' option is present
|
||||||
|
* @param foreground set to 1 if one of the relevant options is present
|
||||||
|
* @return 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
|
||||||
|
int *multithreaded, int *foreground);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go into the background
|
||||||
|
*
|
||||||
|
* @param foreground if true, stay in the foreground
|
||||||
|
* @return 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int fuse_daemonize(int foreground);
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the version of the library
|
* Get the version of the library
|
||||||
*
|
*
|
||||||
|
@ -1079,6 +1079,13 @@ int fuse_req_interrupted(fuse_req_t req);
|
|||||||
* Filesystem setup *
|
* Filesystem setup *
|
||||||
* ----------------------------------------------------------- */
|
* ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
/* Deprecated, don't use */
|
||||||
|
int fuse_lowlevel_is_lib_option(const char *opt);
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a low level session
|
* Create a low level session
|
||||||
*
|
*
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
See the file COPYING.LIB
|
See the file COPYING.LIB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
/* For pthread_rwlock_t */
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "fuse_i.h"
|
#include "fuse_i.h"
|
||||||
#include "fuse_lowlevel.h"
|
#include "fuse_lowlevel.h"
|
||||||
@ -28,6 +33,10 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
#define FUSE_MAX_PATH 4096
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
|
#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
|
||||||
|
|
||||||
#define FUSE_UNKNOWN_INO 0xffffffff
|
#define FUSE_UNKNOWN_INO 0xffffffff
|
||||||
@ -54,13 +63,27 @@ struct fuse_config {
|
|||||||
int intr;
|
int intr;
|
||||||
int intr_signal;
|
int intr_signal;
|
||||||
int help;
|
int help;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
int auto_cache;
|
||||||
|
char *modules;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fuse_fs {
|
struct fuse_fs {
|
||||||
struct fuse_operations op;
|
struct fuse_operations op;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
struct fuse_module *m;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
struct fusemod_so {
|
||||||
|
void *handle;
|
||||||
|
int ctr;
|
||||||
|
};
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
struct fuse {
|
struct fuse {
|
||||||
struct fuse_session *se;
|
struct fuse_session *se;
|
||||||
struct node **name_table;
|
struct node **name_table;
|
||||||
@ -98,6 +121,12 @@ struct node {
|
|||||||
uint64_t nlookup;
|
uint64_t nlookup;
|
||||||
int open_count;
|
int open_count;
|
||||||
int is_hidden;
|
int is_hidden;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
struct timespec stat_updated;
|
||||||
|
struct timespec mtime;
|
||||||
|
off_t size;
|
||||||
|
int cache_valid;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
struct lock *locks;
|
struct lock *locks;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,6 +154,107 @@ static pthread_key_t fuse_context_key;
|
|||||||
static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static int fuse_context_ref;
|
static int fuse_context_ref;
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static struct fusemod_so *fuse_current_so;
|
||||||
|
static struct fuse_module *fuse_modules;
|
||||||
|
|
||||||
|
static int fuse_load_so_name(const char *soname)
|
||||||
|
{
|
||||||
|
struct fusemod_so *so;
|
||||||
|
|
||||||
|
so = calloc(1, sizeof(struct fusemod_so));
|
||||||
|
if (!so) {
|
||||||
|
fprintf(stderr, "fuse: memory allocation failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fuse_current_so = so;
|
||||||
|
so->handle = dlopen(soname, RTLD_NOW);
|
||||||
|
fuse_current_so = NULL;
|
||||||
|
if (!so->handle) {
|
||||||
|
fprintf(stderr, "fuse: %s\n", dlerror());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!so->ctr) {
|
||||||
|
fprintf(stderr, "fuse: %s did not register any modules", soname);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (so->handle)
|
||||||
|
dlclose(so->handle);
|
||||||
|
free(so);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fuse_load_so_module(const char *module)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
char *soname = malloc(strlen(module) + 64);
|
||||||
|
if (!soname) {
|
||||||
|
fprintf(stderr, "fuse: memory allocation failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sprintf(soname, "libfusemod_%s.so", module);
|
||||||
|
res = fuse_load_so_name(soname);
|
||||||
|
free(soname);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct fuse_module *fuse_find_module(const char *module)
|
||||||
|
{
|
||||||
|
struct fuse_module *m;
|
||||||
|
for (m = fuse_modules; m; m = m->next) {
|
||||||
|
if (strcmp(module, m->name) == 0) {
|
||||||
|
m->ctr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct fuse_module *fuse_get_module(const char *module)
|
||||||
|
{
|
||||||
|
struct fuse_module *m;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&fuse_context_lock);
|
||||||
|
m = fuse_find_module(module);
|
||||||
|
if (!m) {
|
||||||
|
int err = fuse_load_so_module(module);
|
||||||
|
if (!err)
|
||||||
|
m = fuse_find_module(module);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&fuse_context_lock);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fuse_put_module(struct fuse_module *m)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&fuse_context_lock);
|
||||||
|
assert(m->ctr > 0);
|
||||||
|
m->ctr--;
|
||||||
|
if (!m->ctr && m->so) {
|
||||||
|
struct fusemod_so *so = m->so;
|
||||||
|
assert(so->ctr > 0);
|
||||||
|
so->ctr--;
|
||||||
|
if (!so->ctr) {
|
||||||
|
struct fuse_module **mp;
|
||||||
|
for (mp = &fuse_modules; *mp;) {
|
||||||
|
if ((*mp)->so == so)
|
||||||
|
*mp = (*mp)->next;
|
||||||
|
else
|
||||||
|
mp = &(*mp)->next;
|
||||||
|
}
|
||||||
|
dlclose(so->handle);
|
||||||
|
free(so);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&fuse_context_lock);
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
|
static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
|
||||||
{
|
{
|
||||||
size_t hash = nodeid % f->id_table_size;
|
size_t hash = nodeid % f->id_table_size;
|
||||||
@ -297,10 +427,15 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOLARIS__
|
||||||
static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
|
static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
static char *add_name(char *buf, char *s, const char *name)
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
{
|
{
|
||||||
size_t len = strlen(name);
|
size_t len = strlen(name);
|
||||||
|
|
||||||
|
#ifndef __SOLARIS__
|
||||||
if (s - len <= *buf) {
|
if (s - len <= *buf) {
|
||||||
unsigned pathlen = *bufsize - (s - *buf);
|
unsigned pathlen = *bufsize - (s - *buf);
|
||||||
unsigned newbufsize = *bufsize;
|
unsigned newbufsize = *bufsize;
|
||||||
@ -323,6 +458,13 @@ static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
|
|||||||
*bufsize = newbufsize;
|
*bufsize = newbufsize;
|
||||||
}
|
}
|
||||||
s -= len;
|
s -= len;
|
||||||
|
#else /* ! __SOLARIS__ */
|
||||||
|
s -= len;
|
||||||
|
if (s <= buf) {
|
||||||
|
fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
strncpy(s, name, len);
|
strncpy(s, name, len);
|
||||||
s--;
|
s--;
|
||||||
*s = '/';
|
*s = '/';
|
||||||
@ -332,6 +474,42 @@ static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
|
|||||||
|
|
||||||
static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
|
static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
|
||||||
{
|
{
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
char buf[FUSE_MAX_PATH];
|
||||||
|
char *s = buf + FUSE_MAX_PATH - 1;
|
||||||
|
struct node *node;
|
||||||
|
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
|
if (name != NULL) {
|
||||||
|
s = add_name(buf, s, name);
|
||||||
|
if (s == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
|
||||||
|
node = node->parent) {
|
||||||
|
if (node->name == NULL) {
|
||||||
|
s = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = add_name(buf, s, node->name);
|
||||||
|
if (s == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
|
||||||
|
if (node == NULL || s == NULL)
|
||||||
|
return NULL;
|
||||||
|
else if (*s == '\0')
|
||||||
|
return strdup("/");
|
||||||
|
else
|
||||||
|
return strdup(s);
|
||||||
|
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
|
||||||
unsigned bufsize = 256;
|
unsigned bufsize = 256;
|
||||||
char *buf;
|
char *buf;
|
||||||
char *s;
|
char *s;
|
||||||
@ -376,6 +554,7 @@ static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
|
|||||||
out_free:
|
out_free:
|
||||||
free(buf);
|
free(buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_path(struct fuse *f, fuse_ino_t nodeid)
|
static char *get_path(struct fuse *f, fuse_ino_t nodeid)
|
||||||
@ -930,6 +1109,44 @@ static int hide_node(struct fuse *f, const char *oldpath,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
|
||||||
|
{
|
||||||
|
return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CLOCK_MONOTONIC
|
||||||
|
#define CLOCK_MONOTONIC CLOCK_REALTIME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void curr_time(struct timespec *now)
|
||||||
|
{
|
||||||
|
static clockid_t clockid = CLOCK_MONOTONIC;
|
||||||
|
int res = clock_gettime(clockid, now);
|
||||||
|
if (res == -1 && errno == EINVAL) {
|
||||||
|
clockid = CLOCK_REALTIME;
|
||||||
|
res = clock_gettime(clockid, now);
|
||||||
|
}
|
||||||
|
if (res == -1) {
|
||||||
|
perror("fuse: clock_gettime");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_stat(struct node *node, const struct stat *stbuf)
|
||||||
|
{
|
||||||
|
if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
|
||||||
|
stbuf->st_size != node->size))
|
||||||
|
node->cache_valid = 0;
|
||||||
|
node->mtime.tv_sec = stbuf->st_mtime;
|
||||||
|
node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
|
||||||
|
node->size = stbuf->st_size;
|
||||||
|
curr_time(&node->stat_updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
|
static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
|
||||||
const char *name, const char *path,
|
const char *name, const char *path,
|
||||||
struct fuse_entry_param *e, struct fuse_file_info *fi)
|
struct fuse_entry_param *e, struct fuse_file_info *fi)
|
||||||
@ -952,6 +1169,13 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
|
|||||||
e->generation = node->generation;
|
e->generation = node->generation;
|
||||||
e->entry_timeout = f->conf.entry_timeout;
|
e->entry_timeout = f->conf.entry_timeout;
|
||||||
e->attr_timeout = f->conf.attr_timeout;
|
e->attr_timeout = f->conf.attr_timeout;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (f->conf.auto_cache) {
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
update_stat(node, &e->attr);
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
set_stat(f, e->ino, &e->attr);
|
set_stat(f, e->ino, &e->attr);
|
||||||
if (f->conf.debug)
|
if (f->conf.debug)
|
||||||
fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino);
|
fprintf(stderr, " NODEID: %lu\n", (unsigned long) e->ino);
|
||||||
@ -1028,7 +1252,11 @@ static struct fuse *req_fuse_prepare(fuse_req_t req)
|
|||||||
return c->ctx.fuse;
|
return c->ctx.fuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOLARIS__
|
||||||
static void reply_err(fuse_req_t req, int err)
|
static void reply_err(fuse_req_t req, int err)
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
static inline void reply_err(fuse_req_t req, int err)
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
{
|
{
|
||||||
/* fuse_reply_err() uses non-negated errno values */
|
/* fuse_reply_err() uses non-negated errno values */
|
||||||
fuse_reply_err(req, -err);
|
fuse_reply_err(req, -err);
|
||||||
@ -1067,6 +1295,10 @@ void fuse_fs_destroy(struct fuse_fs *fs)
|
|||||||
fuse_get_context()->private_data = fs->user_data;
|
fuse_get_context()->private_data = fs->user_data;
|
||||||
if (fs->op.destroy)
|
if (fs->op.destroy)
|
||||||
fs->op.destroy(fs->user_data);
|
fs->op.destroy(fs->user_data);
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (fs->m)
|
||||||
|
fuse_put_module(fs->m);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
free(fs);
|
free(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,6 +1375,13 @@ static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
|
|||||||
}
|
}
|
||||||
pthread_rwlock_unlock(&f->tree_lock);
|
pthread_rwlock_unlock(&f->tree_lock);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (f->conf.auto_cache) {
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
update_stat(get_node(f, ino), &buf);
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
set_stat(f, ino, &buf);
|
set_stat(f, ino, &buf);
|
||||||
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
||||||
} else
|
} else
|
||||||
@ -1227,6 +1466,13 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
|||||||
}
|
}
|
||||||
pthread_rwlock_unlock(&f->tree_lock);
|
pthread_rwlock_unlock(&f->tree_lock);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (f->conf.auto_cache) {
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
update_stat(get_node(f, ino), &buf);
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
set_stat(f, ino, &buf);
|
set_stat(f, ino, &buf);
|
||||||
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
||||||
} else
|
} else
|
||||||
@ -1571,6 +1817,47 @@ static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
|
|||||||
pthread_rwlock_unlock(&f->tree_lock);
|
pthread_rwlock_unlock(&f->tree_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static double diff_timespec(const struct timespec *t1,
|
||||||
|
const struct timespec *t2)
|
||||||
|
{
|
||||||
|
return (t1->tv_sec - t2->tv_sec) +
|
||||||
|
((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
struct node *node;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
node = get_node(f, ino);
|
||||||
|
if (node->cache_valid) {
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
|
curr_time(&now);
|
||||||
|
if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {
|
||||||
|
struct stat stbuf;
|
||||||
|
int err;
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
|
||||||
|
pthread_mutex_lock(&f->lock);
|
||||||
|
if (!err)
|
||||||
|
update_stat(node, &stbuf);
|
||||||
|
else
|
||||||
|
node->cache_valid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node->cache_valid)
|
||||||
|
fi->keep_cache = 1;
|
||||||
|
|
||||||
|
node->cache_valid = 1;
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
|
static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
|
||||||
struct fuse_file_info *fi)
|
struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
@ -1590,6 +1877,11 @@ static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
fi->direct_io = 1;
|
fi->direct_io = 1;
|
||||||
if (f->conf.kernel_cache)
|
if (f->conf.kernel_cache)
|
||||||
fi->keep_cache = 1;
|
fi->keep_cache = 1;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
if (f->conf.auto_cache)
|
||||||
|
open_auto_cache(f, ino, path, fi);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
}
|
}
|
||||||
fuse_finish_interrupt(f, req, &d);
|
fuse_finish_interrupt(f, req, &d);
|
||||||
}
|
}
|
||||||
@ -1775,7 +2067,9 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reply_err(req, err);
|
reply_err(req, err);
|
||||||
|
#ifndef __SOLARIS__
|
||||||
pthread_mutex_destroy(&dh->lock);
|
pthread_mutex_destroy(&dh->lock);
|
||||||
|
#endif /* ! __SOLARIS__ */
|
||||||
free(dh);
|
free(dh);
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
@ -1789,12 +2083,17 @@ static int extend_contents(struct fuse_dh *dh, unsigned minsize)
|
|||||||
unsigned newsize = dh->size;
|
unsigned newsize = dh->size;
|
||||||
if (!newsize)
|
if (!newsize)
|
||||||
newsize = 1024;
|
newsize = 1024;
|
||||||
|
#ifndef __SOLARIS__
|
||||||
while (newsize < minsize) {
|
while (newsize < minsize) {
|
||||||
if (newsize >= 0x80000000)
|
if (newsize >= 0x80000000)
|
||||||
newsize = 0xffffffff;
|
newsize = 0xffffffff;
|
||||||
else
|
else
|
||||||
newsize *= 2;
|
newsize *= 2;
|
||||||
}
|
}
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
while (newsize < minsize)
|
||||||
|
newsize *= 2;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
newptr = (char *) realloc(dh->contents, newsize);
|
newptr = (char *) realloc(dh->contents, newsize);
|
||||||
if (!newptr) {
|
if (!newptr) {
|
||||||
@ -2501,6 +2800,10 @@ static const struct fuse_opt fuse_lib_opts[] = {
|
|||||||
FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
|
FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
|
||||||
FUSE_LIB_OPT("direct_io", direct_io, 1),
|
FUSE_LIB_OPT("direct_io", direct_io, 1),
|
||||||
FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
|
FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
FUSE_LIB_OPT("auto_cache", auto_cache, 1),
|
||||||
|
FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
FUSE_LIB_OPT("umask=", set_mode, 1),
|
FUSE_LIB_OPT("umask=", set_mode, 1),
|
||||||
FUSE_LIB_OPT("umask=%o", umask, 0),
|
FUSE_LIB_OPT("umask=%o", umask, 0),
|
||||||
FUSE_LIB_OPT("uid=", set_uid, 1),
|
FUSE_LIB_OPT("uid=", set_uid, 1),
|
||||||
@ -2514,6 +2817,9 @@ static const struct fuse_opt fuse_lib_opts[] = {
|
|||||||
FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
|
FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
|
||||||
FUSE_LIB_OPT("intr", intr, 1),
|
FUSE_LIB_OPT("intr", intr, 1),
|
||||||
FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
|
FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
FUSE_LIB_OPT("modules=%s", modules, 0),
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
FUSE_OPT_END
|
FUSE_OPT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2525,6 +2831,9 @@ static void fuse_lib_help(void)
|
|||||||
" -o readdir_ino try to fill in d_ino in readdir\n"
|
" -o readdir_ino try to fill in d_ino in readdir\n"
|
||||||
" -o direct_io use direct I/O\n"
|
" -o direct_io use direct I/O\n"
|
||||||
" -o kernel_cache cache files in kernel\n"
|
" -o kernel_cache cache files in kernel\n"
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
" -o [no]auto_cache enable caching based on modification times\n"
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
" -o umask=M set file permissions (octal)\n"
|
" -o umask=M set file permissions (octal)\n"
|
||||||
" -o uid=N set file owner\n"
|
" -o uid=N set file owner\n"
|
||||||
" -o gid=N set file group\n"
|
" -o gid=N set file group\n"
|
||||||
@ -2534,9 +2843,42 @@ static void fuse_lib_help(void)
|
|||||||
" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
|
" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
|
||||||
" -o intr allow requests to be interrupted\n"
|
" -o intr allow requests to be interrupted\n"
|
||||||
" -o intr_signal=NUM signal to send on interrupt (%i)\n"
|
" -o intr_signal=NUM signal to send on interrupt (%i)\n"
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
"\n", FUSE_DEFAULT_INTR_SIGNAL);
|
"\n", FUSE_DEFAULT_INTR_SIGNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static void fuse_lib_help_modules(void)
|
||||||
|
{
|
||||||
|
struct fuse_module *m;
|
||||||
|
fprintf(stderr, "\nModule options:\n");
|
||||||
|
pthread_mutex_lock(&fuse_context_lock);
|
||||||
|
for (m = fuse_modules; m; m = m->next) {
|
||||||
|
struct fuse_fs *fs = NULL;
|
||||||
|
struct fuse_fs *newfs;
|
||||||
|
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
||||||
|
if (fuse_opt_add_arg(&args, "") != -1 &&
|
||||||
|
fuse_opt_add_arg(&args, "-h") != -1) {
|
||||||
|
fprintf(stderr, "\n[%s]\n", m->name);
|
||||||
|
newfs = m->factory(&args, &fs);
|
||||||
|
assert(newfs == NULL);
|
||||||
|
}
|
||||||
|
fuse_opt_free_args(&args);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&fuse_context_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fuse_is_lib_option(const char *opt)
|
||||||
|
{
|
||||||
|
return fuse_lowlevel_is_lib_option(opt) ||
|
||||||
|
fuse_opt_match(fuse_lib_opts, opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static int fuse_lib_opt_proc(void *data, const char *arg, int key,
|
static int fuse_lib_opt_proc(void *data, const char *arg, int key,
|
||||||
struct fuse_args *outargs)
|
struct fuse_args *outargs)
|
||||||
{
|
{
|
||||||
@ -2585,6 +2927,32 @@ static void fuse_restore_intr_signal(int signum)
|
|||||||
sigaction(signum, &sa, NULL);
|
sigaction(signum, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static int fuse_push_module(struct fuse *f, const char *module,
|
||||||
|
struct fuse_args *args)
|
||||||
|
{
|
||||||
|
struct fuse_fs *newfs;
|
||||||
|
struct fuse_module *m = fuse_get_module(module);
|
||||||
|
struct fuse_fs *fs[2];
|
||||||
|
|
||||||
|
fs[0] = f->fs;
|
||||||
|
fs[1] = NULL;
|
||||||
|
if (!m)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
newfs = m->factory(args, fs);
|
||||||
|
if (!newfs) {
|
||||||
|
fuse_put_module(m);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
newfs->m = m;
|
||||||
|
f->fs = newfs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
|
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
@ -2646,6 +3014,22 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
|
|||||||
if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
|
if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
|
||||||
goto out_free_fs;
|
goto out_free_fs;
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (f->conf.modules) {
|
||||||
|
char *module;
|
||||||
|
char *next;
|
||||||
|
|
||||||
|
for (module = f->conf.modules; module; module = next) {
|
||||||
|
char *p;
|
||||||
|
for (p = module; *p && *p != ':'; p++);
|
||||||
|
next = *p ? p + 1 : NULL;
|
||||||
|
*p = '\0';
|
||||||
|
if (module[0] && fuse_push_module(f, module, args) == -1)
|
||||||
|
goto out_free_fs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
if (!f->conf.ac_attr_timeout_set)
|
if (!f->conf.ac_attr_timeout_set)
|
||||||
f->conf.ac_attr_timeout = f->conf.attr_timeout;
|
f->conf.ac_attr_timeout = f->conf.attr_timeout;
|
||||||
|
|
||||||
@ -2658,14 +3042,21 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
|
f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
|
||||||
|
|
||||||
if (f->se == NULL) {
|
if (f->se == NULL) {
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
if (f->conf.help)
|
||||||
|
fuse_lib_help_modules();
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
goto out_free_fs;
|
goto out_free_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
fuse_session_add_chan(f->se, ch);
|
fuse_session_add_chan(f->se, ch);
|
||||||
|
|
||||||
|
#ifndef __SOLARIS__
|
||||||
if (f->conf.debug)
|
if (f->conf.debug)
|
||||||
fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
|
fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
|
||||||
|
#endif /* ! __SOLARIS__ */
|
||||||
f->ctr = 0;
|
f->ctr = 0;
|
||||||
f->generation = 0;
|
f->generation = 0;
|
||||||
/* FIXME: Dynamic hash table */
|
/* FIXME: Dynamic hash table */
|
||||||
@ -2728,6 +3119,9 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
|
|||||||
called on the filesystem without init being called first */
|
called on the filesystem without init being called first */
|
||||||
fs->op.destroy = NULL;
|
fs->op.destroy = NULL;
|
||||||
fuse_fs_destroy(f->fs);
|
fuse_fs_destroy(f->fs);
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
free(f->conf.modules);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
out_free:
|
out_free:
|
||||||
free(f);
|
free(f);
|
||||||
out_delete_context_key:
|
out_delete_context_key:
|
||||||
@ -2777,7 +3171,9 @@ void fuse_destroy(struct fuse *f)
|
|||||||
pthread_mutex_destroy(&f->lock);
|
pthread_mutex_destroy(&f->lock);
|
||||||
pthread_rwlock_destroy(&f->tree_lock);
|
pthread_rwlock_destroy(&f->tree_lock);
|
||||||
fuse_session_destroy(f->se);
|
fuse_session_destroy(f->se);
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
free(f->conf.modules);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
free(f);
|
free(f);
|
||||||
fuse_delete_context_key();
|
fuse_delete_context_key();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,18 +1130,6 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
|
|||||||
return &req->ctx;
|
return &req->ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The size of fuse_ctx got extended, so need to be careful about
|
|
||||||
* incompatibility (i.e. a new binary cannot work with an old
|
|
||||||
* library).
|
|
||||||
*/
|
|
||||||
const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req);
|
|
||||||
const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req)
|
|
||||||
{
|
|
||||||
return fuse_req_ctx(req);
|
|
||||||
}
|
|
||||||
//FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4");
|
|
||||||
|
|
||||||
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
|
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
@ -1327,6 +1315,15 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
int fuse_lowlevel_is_lib_option(const char *opt)
|
||||||
|
{
|
||||||
|
return fuse_opt_match(fuse_ll_opts, opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static void fuse_ll_destroy(void *data)
|
static void fuse_ll_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct fuse_ll *f = (struct fuse_ll *) data;
|
struct fuse_ll *f = (struct fuse_ll *) data;
|
||||||
@ -1387,4 +1384,3 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
|
|||||||
out:
|
out:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +165,20 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
|
|||||||
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
|
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct fuse_chan *ch = *chp;
|
struct fuse_chan *ch = *chp;
|
||||||
|
|
||||||
return ch->op.receive(chp, buf, size);
|
return ch->op.receive(chp, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = fuse_chan_recv(&ch, buf, size);
|
||||||
|
return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
|
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
|
||||||
{
|
{
|
||||||
return ch->op.send(ch, iov, count);
|
return ch->op.send(ch, iov, count);
|
||||||
@ -180,4 +191,3 @@ void fuse_chan_destroy(struct fuse_chan *ch)
|
|||||||
ch->op.destroy(ch);
|
ch->op.destroy(ch);
|
||||||
free(ch);
|
free(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,14 +19,20 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
#include <sys/mnttab.h>
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
#include <grp.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
|
#include <sys/fsuid.h>
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/fsuid.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <grp.h>
|
|
||||||
|
|
||||||
#define FUSE_DEV_NEW "/dev/fuse"
|
#define FUSE_DEV_NEW "/dev/fuse"
|
||||||
|
|
||||||
@ -41,6 +47,32 @@ static int mount_max = 1000;
|
|||||||
int drop_privs(void);
|
int drop_privs(void);
|
||||||
int restore_privs(void);
|
int restore_privs(void);
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fusermount is not implemented in fuse-lite for Solaris,
|
||||||
|
* only the minimal functions are provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Solaris doesn't have setfsuid/setfsgid.
|
||||||
|
* This doesn't really matter anyway as this program shouldn't be made
|
||||||
|
* suid on Solaris. It should instead be used via a profile with the
|
||||||
|
* sys_mount privilege.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int drop_privs(void)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int restore_privs(void)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
|
||||||
static const char *get_user_name(void)
|
static const char *get_user_name(void)
|
||||||
{
|
{
|
||||||
struct passwd *pw = getpwuid(getuid());
|
struct passwd *pw = getpwuid(getuid());
|
||||||
@ -668,3 +700,5 @@ out:
|
|||||||
free(mnt);
|
free(mnt);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
@ -15,6 +15,18 @@ struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args)
|
|||||||
struct fuse_chan *ch;
|
struct fuse_chan *ch;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
/*
|
||||||
|
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
|
||||||
|
* would ensue.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
fd = open("/dev/null", O_RDWR);
|
||||||
|
if (fd > 2)
|
||||||
|
close(fd);
|
||||||
|
} while (fd >= 0 && fd <= 2);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
fd = fuse_kern_mount(mountpoint, args);
|
fd = fuse_kern_mount(mountpoint, args);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -38,3 +50,12 @@ int fuse_version(void)
|
|||||||
return FUSE_VERSION;
|
return FUSE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
#undef fuse_main
|
||||||
|
int fuse_main(void);
|
||||||
|
int fuse_main(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fuse_main(): This function does not exist\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "mount_util.h"
|
#include "mount_util.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -23,6 +24,21 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
#define FUSERMOUNT_PROG "fusermount"
|
||||||
|
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
|
||||||
|
|
||||||
|
#ifndef FUSERMOUNT_DIR
|
||||||
|
#define FUSERMOUNT_DIR "/usr"
|
||||||
|
#endif /* FUSERMOUNT_DIR */
|
||||||
|
|
||||||
|
#ifndef HAVE_FORK
|
||||||
|
#define fork() vfork()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
#ifndef MS_DIRSYNC
|
#ifndef MS_DIRSYNC
|
||||||
#define MS_DIRSYNC 128
|
#define MS_DIRSYNC 128
|
||||||
#endif
|
#endif
|
||||||
@ -44,8 +60,16 @@ struct mount_opts {
|
|||||||
int allow_root;
|
int allow_root;
|
||||||
int ishelp;
|
int ishelp;
|
||||||
int flags;
|
int flags;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
int nonempty;
|
||||||
int blkdev;
|
int blkdev;
|
||||||
char *fsname;
|
char *fsname;
|
||||||
|
char *subtype;
|
||||||
|
char *subtype_opt;
|
||||||
|
#else
|
||||||
|
int blkdev;
|
||||||
|
char *fsname;
|
||||||
|
#endif
|
||||||
char *mtab_opts;
|
char *mtab_opts;
|
||||||
char *fusermount_opts;
|
char *fusermount_opts;
|
||||||
char *kernel_opts;
|
char *kernel_opts;
|
||||||
@ -54,6 +78,42 @@ struct mount_opts {
|
|||||||
#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
|
#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
|
||||||
|
|
||||||
static const struct fuse_opt fuse_mount_opts[] = {
|
static const struct fuse_opt fuse_mount_opts[] = {
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
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("-g", KEY_KERN_FLAG),
|
||||||
|
FUSE_OPT_KEY("-m", KEY_KERN_FLAG),
|
||||||
|
FUSE_OPT_KEY("-O", KEY_KERN_FLAG),
|
||||||
|
FUSE_OPT_KEY("setuid", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("nosetuid", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("devices", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("nodevices", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("exec", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("noexec", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("nbmand", KEY_KERN_OPT),
|
||||||
|
FUSE_OPT_KEY("nonbmand", KEY_KERN_OPT),
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
FUSE_MOUNT_OPT("allow_other", allow_other),
|
FUSE_MOUNT_OPT("allow_other", allow_other),
|
||||||
FUSE_MOUNT_OPT("allow_root", allow_root),
|
FUSE_MOUNT_OPT("allow_root", allow_root),
|
||||||
FUSE_MOUNT_OPT("blkdev", blkdev),
|
FUSE_MOUNT_OPT("blkdev", blkdev),
|
||||||
@ -83,6 +143,7 @@ static const struct fuse_opt fuse_mount_opts[] = {
|
|||||||
FUSE_OPT_KEY("dirsync", KEY_KERN_FLAG),
|
FUSE_OPT_KEY("dirsync", KEY_KERN_FLAG),
|
||||||
FUSE_OPT_KEY("atime", KEY_KERN_FLAG),
|
FUSE_OPT_KEY("atime", KEY_KERN_FLAG),
|
||||||
FUSE_OPT_KEY("noatime", KEY_KERN_FLAG),
|
FUSE_OPT_KEY("noatime", KEY_KERN_FLAG),
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
FUSE_OPT_KEY("-h", KEY_HELP),
|
FUSE_OPT_KEY("-h", KEY_HELP),
|
||||||
FUSE_OPT_KEY("--help", KEY_HELP),
|
FUSE_OPT_KEY("--help", KEY_HELP),
|
||||||
FUSE_OPT_KEY("-V", KEY_VERSION),
|
FUSE_OPT_KEY("-V", KEY_VERSION),
|
||||||
@ -90,6 +151,42 @@ static const struct fuse_opt fuse_mount_opts[] = {
|
|||||||
FUSE_OPT_END
|
FUSE_OPT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static void mount_help(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
" -o allow_other allow access to other users\n"
|
||||||
|
" -o allow_root allow access to root\n"
|
||||||
|
" -o nonempty allow mounts over non-empty file/dir\n"
|
||||||
|
" -o default_permissions enable permission checking by kernel\n"
|
||||||
|
" -o fsname=NAME set filesystem name\n"
|
||||||
|
" -o subtype=NAME set filesystem type\n"
|
||||||
|
" -o large_read issue large read requests (2.4 only)\n"
|
||||||
|
" -o max_read=N set maximum size of read requests\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exec_fusermount(const char *argv[])
|
||||||
|
{
|
||||||
|
execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
|
||||||
|
execvp(FUSERMOUNT_PROG, (char **) argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mount_version(void)
|
||||||
|
{
|
||||||
|
int pid = fork();
|
||||||
|
if (!pid) {
|
||||||
|
const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL };
|
||||||
|
exec_fusermount(argv);
|
||||||
|
_exit(1);
|
||||||
|
} else if (pid != -1)
|
||||||
|
waitpid(pid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
struct mount_flags {
|
struct mount_flags {
|
||||||
const char *opt;
|
const char *opt;
|
||||||
unsigned long flag;
|
unsigned long flag;
|
||||||
@ -101,6 +198,7 @@ static struct mount_flags mount_flags[] = {
|
|||||||
{"ro", MS_RDONLY, 1},
|
{"ro", MS_RDONLY, 1},
|
||||||
{"suid", MS_NOSUID, 0},
|
{"suid", MS_NOSUID, 0},
|
||||||
{"nosuid", MS_NOSUID, 1},
|
{"nosuid", MS_NOSUID, 1},
|
||||||
|
#ifndef __SOLARIS__
|
||||||
{"dev", MS_NODEV, 0},
|
{"dev", MS_NODEV, 0},
|
||||||
{"nodev", MS_NODEV, 1},
|
{"nodev", MS_NODEV, 1},
|
||||||
{"exec", MS_NOEXEC, 0},
|
{"exec", MS_NOEXEC, 0},
|
||||||
@ -110,9 +208,42 @@ static struct mount_flags mount_flags[] = {
|
|||||||
{"atime", MS_NOATIME, 0},
|
{"atime", MS_NOATIME, 0},
|
||||||
{"noatime", MS_NOATIME, 1},
|
{"noatime", MS_NOATIME, 1},
|
||||||
{"dirsync", MS_DIRSYNC, 1},
|
{"dirsync", MS_DIRSYNC, 1},
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
{"-g", MS_GLOBAL, 1}, /* 1eaf4 */
|
||||||
|
{"-m", MS_NOMNTTAB, 1}, /* 1eb00 */
|
||||||
|
{"-O", MS_OVERLAY, 1}, /* 1eb0c */
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
{NULL, 0, 0}
|
{NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See comments in fuse_kern_mount()
|
||||||
|
*/
|
||||||
|
struct solaris_mount_opts {
|
||||||
|
int nosuid;
|
||||||
|
int setuid;
|
||||||
|
int nosetuid;
|
||||||
|
int devices;
|
||||||
|
int nodevices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SOLARIS_MOUNT_OPT(t, p, n) \
|
||||||
|
{ t, offsetof(struct solaris_mount_opts, p), n }
|
||||||
|
static const struct fuse_opt solaris_mnt_opts[] = {
|
||||||
|
SOLARIS_MOUNT_OPT("suid", setuid, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("suid", devices, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("nosuid", nosuid, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("setuid", setuid, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("nosetuid", nosetuid, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("devices", devices, 1),
|
||||||
|
SOLARIS_MOUNT_OPT("nodevices", nodevices, 1),
|
||||||
|
FUSE_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static void set_mount_flag(const char *s, int *flags)
|
static void set_mount_flag(const char *s, int *flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -156,23 +287,85 @@ static int fuse_mount_opt_proc(void *data, const char *arg, int key,
|
|||||||
case KEY_FUSERMOUNT_OPT:
|
case KEY_FUSERMOUNT_OPT:
|
||||||
return fuse_opt_add_opt(&mo->fusermount_opts, arg);
|
return fuse_opt_add_opt(&mo->fusermount_opts, arg);
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
case KEY_SUBTYPE_OPT:
|
||||||
|
return fuse_opt_add_opt(&mo->subtype_opt, arg);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
case KEY_MTAB_OPT:
|
case KEY_MTAB_OPT:
|
||||||
return fuse_opt_add_opt(&mo->mtab_opts, arg);
|
return fuse_opt_add_opt(&mo->mtab_opts, arg);
|
||||||
|
|
||||||
case KEY_HELP:
|
case KEY_HELP:
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
mount_help();
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
mo->ishelp = 1;
|
mo->ishelp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_VERSION:
|
case KEY_VERSION:
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
mount_version();
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
mo->ishelp = 1;
|
mo->ishelp = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
/* return value:
|
||||||
|
* >= 0 => fd
|
||||||
|
* -1 => error
|
||||||
|
*/
|
||||||
|
static int receive_fd(int fd)
|
||||||
|
{
|
||||||
|
struct msghdr msg;
|
||||||
|
struct iovec iov;
|
||||||
|
char buf[1];
|
||||||
|
int rv;
|
||||||
|
size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
|
iov.iov_base = buf;
|
||||||
|
iov.iov_len = 1;
|
||||||
|
|
||||||
|
msg.msg_name = 0;
|
||||||
|
msg.msg_namelen = 0;
|
||||||
|
msg.msg_iov = &iov;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
/* old BSD implementations should use msg_accrights instead of
|
||||||
|
* msg_control; the interface is different. */
|
||||||
|
msg.msg_control = ccmsg;
|
||||||
|
msg.msg_controllen = sizeof(ccmsg);
|
||||||
|
|
||||||
|
while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
|
||||||
|
if (rv == -1) {
|
||||||
|
perror("recvmsg");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!rv) {
|
||||||
|
/* EOF */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
if (!cmsg->cmsg_type == SCM_RIGHTS) {
|
||||||
|
fprintf(stderr, "got control message of unknown type %d\n",
|
||||||
|
cmsg->cmsg_type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return *(int*)CMSG_DATA(cmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
void fuse_kern_unmount(const char *mountpoint, int fd)
|
void fuse_kern_unmount(const char *mountpoint, int fd)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
int pid;
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
if (!mountpoint)
|
if (!mountpoint)
|
||||||
return;
|
return;
|
||||||
@ -188,11 +381,214 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
|
|||||||
if (res == 1 && (pfd.revents & POLLERR))
|
if (res == 1 && (pfd.revents & POLLERR))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifndef __SOLARIS__
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
fusermount(1, 0, 1, "", mountpoint);
|
fusermount(1, 0, 1, "", mountpoint);
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
if (geteuid() == 0) {
|
||||||
|
fuse_mnt_umount("fuse", mountpoint, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = umount2(mountpoint, 2);
|
||||||
|
if (res == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if(pid == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pid == 0) {
|
||||||
|
const char *argv[] =
|
||||||
|
{ FUSERMOUNT_PROG, "-u", "-q", "-z", "--", mountpoint, NULL };
|
||||||
|
|
||||||
|
exec_fusermount(argv);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
waitpid(pid, NULL, 0);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
static int fuse_mount_fusermount(const char *mountpoint, const char *opts,
|
||||||
|
int quiet)
|
||||||
|
{
|
||||||
|
int fds[2], pid;
|
||||||
|
int res;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!mountpoint) {
|
||||||
|
fprintf(stderr, "fuse: missing mountpoint\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
|
||||||
|
if(res == -1) {
|
||||||
|
perror("fuse: socketpair() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if(pid == -1) {
|
||||||
|
perror("fuse: fork() failed");
|
||||||
|
close(fds[0]);
|
||||||
|
close(fds[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pid == 0) {
|
||||||
|
char env[10];
|
||||||
|
const char *argv[32];
|
||||||
|
int a = 0;
|
||||||
|
|
||||||
|
if (quiet) {
|
||||||
|
int fd = open("/dev/null", O_RDONLY);
|
||||||
|
dup2(fd, 1);
|
||||||
|
dup2(fd, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[a++] = FUSERMOUNT_PROG;
|
||||||
|
if (opts) {
|
||||||
|
argv[a++] = "-o";
|
||||||
|
argv[a++] = opts;
|
||||||
|
}
|
||||||
|
argv[a++] = "--";
|
||||||
|
argv[a++] = mountpoint;
|
||||||
|
argv[a++] = NULL;
|
||||||
|
|
||||||
|
close(fds[1]);
|
||||||
|
fcntl(fds[0], F_SETFD, 0);
|
||||||
|
snprintf(env, sizeof(env), "%i", fds[0]);
|
||||||
|
setenv(FUSE_COMMFD_ENV, env, 1);
|
||||||
|
exec_fusermount(argv);
|
||||||
|
perror("fuse: failed to exec fusermount");
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fds[0]);
|
||||||
|
rv = receive_fd(fds[1]);
|
||||||
|
close(fds[1]);
|
||||||
|
waitpid(pid, NULL, 0); /* bury zombie */
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
|
||||||
|
const char *mnt_opts)
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
const char *devname = "/dev/fuse";
|
||||||
|
char *source = NULL;
|
||||||
|
char *type = NULL;
|
||||||
|
struct stat stbuf;
|
||||||
|
int fd;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!mnt) {
|
||||||
|
fprintf(stderr, "fuse: missing mountpoint\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = lstat(mnt, &stbuf);
|
||||||
|
if (res == -1) {
|
||||||
|
fprintf(stderr ,"fuse: failed to access mountpoint %s: %s\n",
|
||||||
|
mnt, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mo->nonempty) {
|
||||||
|
res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode, stbuf.st_size);
|
||||||
|
if (res == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(devname, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
if (errno == ENODEV || errno == ENOENT)
|
||||||
|
fprintf(stderr,
|
||||||
|
"fuse: device not found, try 'modprobe fuse' first\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "fuse: failed to open %s: %s\n", devname,
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd,
|
||||||
|
stbuf.st_mode & S_IFMT, getuid(), getgid());
|
||||||
|
|
||||||
|
res = fuse_opt_add_opt(&mo->kernel_opts, tmp);
|
||||||
|
if (res == -1)
|
||||||
|
goto out_close;
|
||||||
|
|
||||||
|
source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
|
||||||
|
(mo->subtype ? strlen(mo->subtype) : 0) +
|
||||||
|
strlen(devname) + 32);
|
||||||
|
|
||||||
|
type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
|
||||||
|
if (!type || !source) {
|
||||||
|
fprintf(stderr, "fuse: failed to allocate memory\n");
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
|
||||||
|
if (mo->subtype) {
|
||||||
|
strcat(type, ".");
|
||||||
|
strcat(type, mo->subtype);
|
||||||
|
}
|
||||||
|
strcpy(source,
|
||||||
|
mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));
|
||||||
|
|
||||||
|
/* JPA added two final zeroes */
|
||||||
|
res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
|
||||||
|
mo->kernel_opts, MAX_MNTOPT_STR, 0, 0);
|
||||||
|
|
||||||
|
if (res == -1 && errno == EINVAL && mo->subtype) {
|
||||||
|
/* Probably missing subtype support */
|
||||||
|
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
|
||||||
|
if (mo->fsname) {
|
||||||
|
if (!mo->blkdev)
|
||||||
|
sprintf(source, "%s#%s", mo->subtype, mo->fsname);
|
||||||
|
} else {
|
||||||
|
strcpy(source, type);
|
||||||
|
}
|
||||||
|
/* JPA two null args added */
|
||||||
|
res = mount(source, mnt, MS_OPTIONSTR|mo->flags, type, NULL, 0,
|
||||||
|
mo->kernel_opts, MAX_MNTOPT_STR, 0, 0);
|
||||||
|
}
|
||||||
|
if (res == -1) {
|
||||||
|
/*
|
||||||
|
* Maybe kernel doesn't support unprivileged mounts, in this
|
||||||
|
* case try falling back to fusermount
|
||||||
|
*/
|
||||||
|
if (errno == EPERM) {
|
||||||
|
res = -2;
|
||||||
|
} else {
|
||||||
|
int errno_save = errno;
|
||||||
|
if (mo->blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
|
||||||
|
fprintf(stderr, "fuse: 'fuseblk' support missing\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "fuse: mount failed: %s\n",
|
||||||
|
strerror(errno_save));
|
||||||
|
}
|
||||||
|
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
out_umount:
|
||||||
|
umount2(mnt, 2); /* lazy umount */
|
||||||
|
out_close:
|
||||||
|
free(type);
|
||||||
|
free(source);
|
||||||
|
close(fd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
static int get_mnt_flag_opts(char **mnt_optsp, int flags)
|
static int get_mnt_flag_opts(char **mnt_optsp, int flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -213,14 +609,59 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
|
|||||||
struct mount_opts mo;
|
struct mount_opts mo;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
char *mnt_opts = NULL;
|
char *mnt_opts = NULL;
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
struct solaris_mount_opts smo;
|
||||||
|
struct fuse_args sa = FUSE_ARGS_INIT(0, NULL);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
memset(&mo, 0, sizeof(mo));
|
memset(&mo, 0, sizeof(mo));
|
||||||
|
#ifndef __SOLARIS__
|
||||||
if (getuid())
|
if (getuid())
|
||||||
mo.flags = MS_NOSUID | MS_NODEV;
|
mo.flags = MS_NOSUID | MS_NODEV;
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
mo.flags = 0;
|
||||||
|
memset(&smo, 0, sizeof(smo));
|
||||||
|
if (args != NULL) {
|
||||||
|
while (args->argv[sa.argc] != NULL)
|
||||||
|
fuse_opt_add_arg(&sa, args->argv[sa.argc]);
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
if (args &&
|
if (args &&
|
||||||
fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
|
fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
|
||||||
|
#ifndef __SOLARIS__
|
||||||
return -1;
|
return -1;
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
goto out; /* if SOLARIS, clean up 'sa' */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In Solaris, nosuid is equivalent to nosetuid + nodevices. We only
|
||||||
|
* have MS_NOSUID for mount flags (no MS_(NO)SETUID, etc.). But if
|
||||||
|
* we set that as a default, it restricts specifying just nosetuid
|
||||||
|
* or nodevices; there is no way for the user to specify setuid +
|
||||||
|
* nodevices or vice-verse. So we parse the existing options, then
|
||||||
|
* add restrictive defaults if needed.
|
||||||
|
*/
|
||||||
|
if (fuse_opt_parse(&sa, &smo, solaris_mnt_opts, NULL) == -1)
|
||||||
|
goto out;
|
||||||
|
if (smo.nosuid || (!smo.nodevices && !smo.devices
|
||||||
|
&& !smo.nosetuid && !smo.setuid)) {
|
||||||
|
mo.flags |= MS_NOSUID;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Defaults; if neither nodevices|devices,nosetuid|setuid has
|
||||||
|
* been specified, add the default negative option string. If
|
||||||
|
* both have been specified (i.e., -osuid,nosuid), leave them
|
||||||
|
* alone; the last option will have precedence.
|
||||||
|
*/
|
||||||
|
if (!smo.nodevices && !smo.devices)
|
||||||
|
if (fuse_opt_add_opt(&mo.kernel_opts, "nodevices") == -1)
|
||||||
|
goto out;
|
||||||
|
if (!smo.nosetuid && !smo.setuid)
|
||||||
|
if (fuse_opt_add_opt(&mo.kernel_opts, "nosetuid") == -1)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
if (mo.allow_other && mo.allow_root) {
|
if (mo.allow_other && mo.allow_root) {
|
||||||
fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
|
fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
|
||||||
@ -233,6 +674,7 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
|
|||||||
res = -1;
|
res = -1;
|
||||||
if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1)
|
if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
#ifndef __SOLARIS__
|
||||||
if (!(mo.flags & MS_NODEV) && fuse_opt_add_opt(&mnt_opts, "dev") == -1)
|
if (!(mo.flags & MS_NODEV) && fuse_opt_add_opt(&mnt_opts, "dev") == -1)
|
||||||
goto out;
|
goto out;
|
||||||
if (!(mo.flags & MS_NOSUID) && fuse_opt_add_opt(&mnt_opts, "suid") == -1)
|
if (!(mo.flags & MS_NOSUID) && fuse_opt_add_opt(&mnt_opts, "suid") == -1)
|
||||||
@ -243,15 +685,48 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
|
|||||||
goto out;
|
goto out;
|
||||||
if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) < 0)
|
if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
res = fusermount(0, 0, 0, mnt_opts ? mnt_opts : "", mountpoint);
|
res = fusermount(0, 0, 0, mnt_opts ? mnt_opts : "", mountpoint);
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1)
|
||||||
|
goto out;
|
||||||
|
if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1)
|
||||||
|
goto out;
|
||||||
|
res = fuse_mount_sys(mountpoint, &mo, mnt_opts);
|
||||||
|
if (res == -2) {
|
||||||
|
if (mo.fusermount_opts &&
|
||||||
|
fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (mo.subtype) {
|
||||||
|
char *tmp_opts = NULL;
|
||||||
|
|
||||||
|
res = -1;
|
||||||
|
if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 ||
|
||||||
|
fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) {
|
||||||
|
free(tmp_opts);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = fuse_mount_fusermount(mountpoint, tmp_opts, 1);
|
||||||
|
free(tmp_opts);
|
||||||
|
if (res == -1)
|
||||||
|
res = fuse_mount_fusermount(mountpoint, mnt_opts, 0);
|
||||||
|
} else {
|
||||||
|
res = fuse_mount_fusermount(mountpoint, mnt_opts, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(mnt_opts);
|
free(mnt_opts);
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
fuse_opt_free_args(&sa);
|
||||||
|
free(mo.subtype);
|
||||||
|
free(mo.subtype_opt);
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
free(mo.fsname);
|
free(mo.fsname);
|
||||||
free(mo.fusermount_opts);
|
free(mo.fusermount_opts);
|
||||||
free(mo.kernel_opts);
|
free(mo.kernel_opts);
|
||||||
free(mo.mtab_opts);
|
free(mo.mtab_opts);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,245 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <mntent.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
#include <mntent.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
char *mkdtemp(char *template);
|
||||||
|
|
||||||
|
#ifndef _PATH_MOUNTED
|
||||||
|
#define _PATH_MOUNTED "/etc/mnttab"
|
||||||
|
#endif /* _PATH_MOUNTED */
|
||||||
|
|
||||||
|
#ifndef IGNORE_MTAB
|
||||||
|
static int mtab_needs_update(const char *mnt)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
/* If mtab is within new mount, don't touch it */
|
||||||
|
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
|
||||||
|
_PATH_MOUNTED[strlen(mnt)] == '/')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lstat(_PATH_MOUNTED, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* IGNORE_MTAB */
|
||||||
|
|
||||||
|
int fuse_mnt_add_mount(const char *progname, const char *fsname,
|
||||||
|
const char *mnt, const char *type, const char *opts)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
#ifndef IGNORE_MTAB
|
||||||
|
if (!mtab_needs_update(mnt))
|
||||||
|
return 0;
|
||||||
|
#endif /* IGNORE_MTAB */
|
||||||
|
|
||||||
|
res = fork();
|
||||||
|
if (res == -1) {
|
||||||
|
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
char templ[] = "/tmp/fusermountXXXXXX";
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
setuid(geteuid());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hide in a directory, where mount isn't able to resolve
|
||||||
|
* fsname as a valid path
|
||||||
|
*/
|
||||||
|
tmp = mkdtemp(templ);
|
||||||
|
if (!tmp) {
|
||||||
|
fprintf(stderr, "%s: failed to create temporary directory\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (chdir(tmp)) {
|
||||||
|
fprintf(stderr, "%s: failed to chdir to %s: %s\n",
|
||||||
|
progname, tmp, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rmdir(tmp);
|
||||||
|
execl("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts,
|
||||||
|
fsname, mnt, NULL);
|
||||||
|
fprintf(stderr, "%s: failed to execute /sbin/mount: %s\n", progname,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
res = waitpid(res, &status, 0);
|
||||||
|
if (res == -1) {
|
||||||
|
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (status != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
#ifndef IGNORE_MTAB
|
||||||
|
if (!mtab_needs_update(mnt))
|
||||||
|
return 0;
|
||||||
|
#endif /* IGNORE_MTAB */
|
||||||
|
|
||||||
|
res = fork();
|
||||||
|
if (res == -1) {
|
||||||
|
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
setuid(geteuid());
|
||||||
|
execl("/sbin/umount", "/sbin/umount", !lazy ? "-f" : NULL, mnt,
|
||||||
|
NULL);
|
||||||
|
fprintf(stderr, "%s: failed to execute /sbin/umount: %s\n", progname,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
res = waitpid(res, &status, 0);
|
||||||
|
if (res == -1) {
|
||||||
|
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (status != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
char *copy;
|
||||||
|
char *dst;
|
||||||
|
char *end;
|
||||||
|
char *lastcomp;
|
||||||
|
const char *toresolv;
|
||||||
|
|
||||||
|
if (!orig[0]) {
|
||||||
|
fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy = strdup(orig);
|
||||||
|
if (copy == NULL) {
|
||||||
|
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
toresolv = copy;
|
||||||
|
lastcomp = NULL;
|
||||||
|
for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
|
||||||
|
if (end[0] != '/') {
|
||||||
|
char *tmp;
|
||||||
|
end[1] = '\0';
|
||||||
|
tmp = strrchr(copy, '/');
|
||||||
|
if (tmp == NULL) {
|
||||||
|
lastcomp = copy;
|
||||||
|
toresolv = ".";
|
||||||
|
} else {
|
||||||
|
lastcomp = tmp + 1;
|
||||||
|
if (tmp == copy)
|
||||||
|
toresolv = "/";
|
||||||
|
}
|
||||||
|
if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
|
||||||
|
lastcomp = NULL;
|
||||||
|
toresolv = copy;
|
||||||
|
}
|
||||||
|
else if (tmp)
|
||||||
|
tmp[0] = '\0';
|
||||||
|
}
|
||||||
|
if (realpath(toresolv, buf) == NULL) {
|
||||||
|
fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
|
||||||
|
strerror(errno));
|
||||||
|
free(copy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (lastcomp == NULL)
|
||||||
|
dst = strdup(buf);
|
||||||
|
else {
|
||||||
|
dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
|
||||||
|
if (dst) {
|
||||||
|
unsigned buflen = strlen(buf);
|
||||||
|
if (buflen && buf[buflen-1] == '/')
|
||||||
|
sprintf(dst, "%s%s", buf, lastcomp);
|
||||||
|
else
|
||||||
|
sprintf(dst, "%s/%s", buf, lastcomp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(copy);
|
||||||
|
if (dst == NULL)
|
||||||
|
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fuse_mnt_check_empty(const char *progname, const char *mnt,
|
||||||
|
mode_t rootmode, off_t rootsize)
|
||||||
|
{
|
||||||
|
int isempty = 1;
|
||||||
|
|
||||||
|
if (S_ISDIR(rootmode)) {
|
||||||
|
struct dirent *ent;
|
||||||
|
DIR *dp = opendir(mnt);
|
||||||
|
if (dp == NULL) {
|
||||||
|
fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
|
||||||
|
progname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while ((ent = readdir(dp)) != NULL) {
|
||||||
|
if (strcmp(ent->d_name, ".") != 0 &&
|
||||||
|
strcmp(ent->d_name, "..") != 0) {
|
||||||
|
isempty = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dp);
|
||||||
|
} else if (rootsize)
|
||||||
|
isempty = 0;
|
||||||
|
|
||||||
|
if (!isempty) {
|
||||||
|
fprintf(stderr, "%s: mountpoint is not empty\n", progname);
|
||||||
|
fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fuse_mnt_check_fuseblk(void)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
FILE *f = fopen("/proc/filesystems", "r");
|
||||||
|
if (!f)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), f))
|
||||||
|
if (strstr(buf, "fuseblk\n")) {
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
|
||||||
static int mtab_needs_update(const char *mnt)
|
static int mtab_needs_update(const char *mnt)
|
||||||
{
|
{
|
||||||
@ -217,3 +451,5 @@ int fuse_mnt_check_fuseblk(void)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
@ -14,6 +14,14 @@ int fuse_mnt_umount(const char *progname, const char *mnt, int lazy);
|
|||||||
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
|
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
|
||||||
int fuse_mnt_check_fuseblk(void);
|
int fuse_mnt_check_fuseblk(void);
|
||||||
|
|
||||||
|
#ifdef __SOLARIS__
|
||||||
|
|
||||||
|
int fuse_mnt_check_empty(const char *progname, const char *mnt,
|
||||||
|
mode_t rootmode, off_t rootsize);
|
||||||
|
|
||||||
|
#else /* __SOLARIS__ */
|
||||||
|
|
||||||
int fusermount(int unmount, int quiet, int lazy, const char *opts,
|
int fusermount(int unmount, int quiet, int lazy, const char *opts,
|
||||||
const char *origmnt);
|
const char *origmnt);
|
||||||
|
|
||||||
|
#endif /* __SOLARIS__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user