mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +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])
|
||||
case "${target_os}" in
|
||||
linux*)
|
||||
linux*|solaris*)
|
||||
AC_ARG_WITH(
|
||||
[fuse],
|
||||
[AS_HELP_STRING([--with-fuse=<internal|external>],[Select FUSE library: internal or external @<:@default=internal@:>@])],
|
||||
@ -220,7 +220,7 @@ linux*)
|
||||
[with_fuse="internal"]
|
||||
)
|
||||
;;
|
||||
darwin*|netbsd*|solaris*|kfreebsd*-gnu)
|
||||
darwin*|netbsd*|kfreebsd*-gnu)
|
||||
with_fuse="external"
|
||||
;;
|
||||
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,
|
||||
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... *
|
||||
* ----------------------------------------------------------- */
|
||||
|
@ -32,6 +32,11 @@
|
||||
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
|
||||
#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
|
||||
extern "C" {
|
||||
#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);
|
||||
|
||||
#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
|
||||
*
|
||||
|
@ -1079,6 +1079,13 @@ int fuse_req_interrupted(fuse_req_t req);
|
||||
* Filesystem setup *
|
||||
* ----------------------------------------------------------- */
|
||||
|
||||
#ifdef __SOLARIS__
|
||||
|
||||
/* Deprecated, don't use */
|
||||
int fuse_lowlevel_is_lib_option(const char *opt);
|
||||
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
/**
|
||||
* Create a low level session
|
||||
*
|
||||
|
@ -6,6 +6,11 @@
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#ifdef __SOLARIS__
|
||||
/* For pthread_rwlock_t */
|
||||
#define _GNU_SOURCE
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
#include "config.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
@ -28,6 +33,10 @@
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __SOLARIS__
|
||||
#define FUSE_MAX_PATH 4096
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
|
||||
|
||||
#define FUSE_UNKNOWN_INO 0xffffffff
|
||||
@ -54,13 +63,27 @@ struct fuse_config {
|
||||
int intr;
|
||||
int intr_signal;
|
||||
int help;
|
||||
#ifdef __SOLARIS__
|
||||
int auto_cache;
|
||||
char *modules;
|
||||
#endif /* __SOLARIS__ */
|
||||
};
|
||||
|
||||
struct fuse_fs {
|
||||
struct fuse_operations op;
|
||||
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_session *se;
|
||||
struct node **name_table;
|
||||
@ -98,6 +121,12 @@ struct node {
|
||||
uint64_t nlookup;
|
||||
int open_count;
|
||||
int is_hidden;
|
||||
#ifdef __SOLARIS__
|
||||
struct timespec stat_updated;
|
||||
struct timespec mtime;
|
||||
off_t size;
|
||||
int cache_valid;
|
||||
#endif /* __SOLARIS__ */
|
||||
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 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef __SOLARIS__
|
||||
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);
|
||||
|
||||
#ifndef __SOLARIS__
|
||||
if (s - len <= *buf) {
|
||||
unsigned pathlen = *bufsize - (s - *buf);
|
||||
unsigned newbufsize = *bufsize;
|
||||
@ -323,6 +458,13 @@ static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
|
||||
*bufsize = newbufsize;
|
||||
}
|
||||
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);
|
||||
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)
|
||||
{
|
||||
#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;
|
||||
char *buf;
|
||||
char *s;
|
||||
@ -376,6 +554,7 @@ static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
|
||||
out_free:
|
||||
free(buf);
|
||||
return NULL;
|
||||
#endif /* __SOLARIS__ */
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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,
|
||||
const char *name, const char *path,
|
||||
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->entry_timeout = f->conf.entry_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);
|
||||
if (f->conf.debug)
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef __SOLARIS__
|
||||
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(req, -err);
|
||||
@ -1067,6 +1295,10 @@ void fuse_fs_destroy(struct fuse_fs *fs)
|
||||
fuse_get_context()->private_data = fs->user_data;
|
||||
if (fs->op.destroy)
|
||||
fs->op.destroy(fs->user_data);
|
||||
#ifdef __SOLARIS__
|
||||
if (fs->m)
|
||||
fuse_put_module(fs->m);
|
||||
#endif /* __SOLARIS__ */
|
||||
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);
|
||||
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);
|
||||
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
||||
} 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);
|
||||
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);
|
||||
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
||||
} else
|
||||
@ -1571,6 +1817,47 @@ static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
|
||||
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,
|
||||
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;
|
||||
if (f->conf.kernel_cache)
|
||||
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);
|
||||
}
|
||||
@ -1775,7 +2067,9 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
|
||||
}
|
||||
} else {
|
||||
reply_err(req, err);
|
||||
#ifndef __SOLARIS__
|
||||
pthread_mutex_destroy(&dh->lock);
|
||||
#endif /* ! __SOLARIS__ */
|
||||
free(dh);
|
||||
}
|
||||
free(path);
|
||||
@ -1789,12 +2083,17 @@ static int extend_contents(struct fuse_dh *dh, unsigned minsize)
|
||||
unsigned newsize = dh->size;
|
||||
if (!newsize)
|
||||
newsize = 1024;
|
||||
#ifndef __SOLARIS__
|
||||
while (newsize < minsize) {
|
||||
if (newsize >= 0x80000000)
|
||||
newsize = 0xffffffff;
|
||||
else
|
||||
newsize *= 2;
|
||||
}
|
||||
#else /* __SOLARIS__ */
|
||||
while (newsize < minsize)
|
||||
newsize *= 2;
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
newptr = (char *) realloc(dh->contents, newsize);
|
||||
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("direct_io", direct_io, 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=%o", umask, 0),
|
||||
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("intr", intr, 1),
|
||||
FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
|
||||
#ifdef __SOLARIS__
|
||||
FUSE_LIB_OPT("modules=%s", modules, 0),
|
||||
#endif /* __SOLARIS__ */
|
||||
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 direct_io use direct I/O\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 uid=N set file owner\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 intr allow requests to be interrupted\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);
|
||||
}
|
||||
|
||||
#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,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
@ -2585,6 +2927,32 @@ static void fuse_restore_intr_signal(int signum)
|
||||
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,
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
||||
f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
|
||||
|
||||
if (f->se == NULL) {
|
||||
#ifdef __SOLARIS__
|
||||
if (f->conf.help)
|
||||
fuse_lib_help_modules();
|
||||
#endif /* __SOLARIS__ */
|
||||
goto out_free_fs;
|
||||
}
|
||||
|
||||
fuse_session_add_chan(f->se, ch);
|
||||
|
||||
#ifndef __SOLARIS__
|
||||
if (f->conf.debug)
|
||||
fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
|
||||
#endif /* ! __SOLARIS__ */
|
||||
f->ctr = 0;
|
||||
f->generation = 0;
|
||||
/* 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 */
|
||||
fs->op.destroy = NULL;
|
||||
fuse_fs_destroy(f->fs);
|
||||
#ifdef __SOLARIS__
|
||||
free(f->conf.modules);
|
||||
#endif /* __SOLARIS__ */
|
||||
out_free:
|
||||
free(f);
|
||||
out_delete_context_key:
|
||||
@ -2777,7 +3171,9 @@ void fuse_destroy(struct fuse *f)
|
||||
pthread_mutex_destroy(&f->lock);
|
||||
pthread_rwlock_destroy(&f->tree_lock);
|
||||
fuse_session_destroy(f->se);
|
||||
#ifdef __SOLARIS__
|
||||
free(f->conf.modules);
|
||||
#endif /* __SOLARIS__ */
|
||||
free(f);
|
||||
fuse_delete_context_key();
|
||||
}
|
||||
|
||||
|
@ -1130,18 +1130,6 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
|
||||
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 *data)
|
||||
{
|
||||
@ -1327,6 +1315,15 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key,
|
||||
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)
|
||||
{
|
||||
struct fuse_ll *f = (struct fuse_ll *) data;
|
||||
@ -1387,4 +1384,3 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
|
||||
out:
|
||||
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)
|
||||
{
|
||||
struct fuse_chan *ch = *chp;
|
||||
|
||||
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)
|
||||
{
|
||||
return ch->op.send(ch, iov, count);
|
||||
@ -180,4 +191,3 @@ void fuse_chan_destroy(struct fuse_chan *ch)
|
||||
ch->op.destroy(ch);
|
||||
free(ch);
|
||||
}
|
||||
|
||||
|
@ -19,14 +19,20 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#ifdef __SOLARIS__
|
||||
#include <sys/mnttab.h>
|
||||
#else /* __SOLARIS__ */
|
||||
#include <grp.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/fsuid.h>
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/fsuid.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define FUSE_DEV_NEW "/dev/fuse"
|
||||
|
||||
@ -41,6 +47,32 @@ static int mount_max = 1000;
|
||||
int drop_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)
|
||||
{
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
@ -668,3 +700,5 @@ out:
|
||||
free(mnt);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* __SOLARIS__ */
|
||||
|
@ -15,6 +15,18 @@ struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args)
|
||||
struct fuse_chan *ch;
|
||||
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);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
@ -38,3 +50,12 @@ int fuse_version(void)
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
@ -23,6 +24,21 @@
|
||||
#include <sys/wait.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
|
||||
#define MS_DIRSYNC 128
|
||||
#endif
|
||||
@ -44,8 +60,16 @@ struct mount_opts {
|
||||
int allow_root;
|
||||
int ishelp;
|
||||
int flags;
|
||||
#ifdef __SOLARIS__
|
||||
int nonempty;
|
||||
int blkdev;
|
||||
char *fsname;
|
||||
char *subtype;
|
||||
char *subtype_opt;
|
||||
#else
|
||||
int blkdev;
|
||||
char *fsname;
|
||||
#endif
|
||||
char *mtab_opts;
|
||||
char *fusermount_opts;
|
||||
char *kernel_opts;
|
||||
@ -54,6 +78,42 @@ struct mount_opts {
|
||||
#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
|
||||
|
||||
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_root", allow_root),
|
||||
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("atime", KEY_KERN_FLAG),
|
||||
FUSE_OPT_KEY("noatime", KEY_KERN_FLAG),
|
||||
#endif /* __SOLARIS__ */
|
||||
FUSE_OPT_KEY("-h", KEY_HELP),
|
||||
FUSE_OPT_KEY("--help", KEY_HELP),
|
||||
FUSE_OPT_KEY("-V", KEY_VERSION),
|
||||
@ -90,6 +151,42 @@ static const struct fuse_opt fuse_mount_opts[] = {
|
||||
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 {
|
||||
const char *opt;
|
||||
unsigned long flag;
|
||||
@ -101,6 +198,7 @@ static struct mount_flags mount_flags[] = {
|
||||
{"ro", MS_RDONLY, 1},
|
||||
{"suid", MS_NOSUID, 0},
|
||||
{"nosuid", MS_NOSUID, 1},
|
||||
#ifndef __SOLARIS__
|
||||
{"dev", MS_NODEV, 0},
|
||||
{"nodev", MS_NODEV, 1},
|
||||
{"exec", MS_NOEXEC, 0},
|
||||
@ -110,9 +208,42 @@ static struct mount_flags mount_flags[] = {
|
||||
{"atime", MS_NOATIME, 0},
|
||||
{"noatime", MS_NOATIME, 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}
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
int i;
|
||||
@ -156,23 +287,85 @@ static int fuse_mount_opt_proc(void *data, const char *arg, int key,
|
||||
case KEY_FUSERMOUNT_OPT:
|
||||
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:
|
||||
return fuse_opt_add_opt(&mo->mtab_opts, arg);
|
||||
|
||||
case KEY_HELP:
|
||||
#ifdef __SOLARIS__
|
||||
mount_help();
|
||||
#endif /* __SOLARIS__ */
|
||||
mo->ishelp = 1;
|
||||
break;
|
||||
|
||||
case KEY_VERSION:
|
||||
#ifdef __SOLARIS__
|
||||
mount_version();
|
||||
#endif /* __SOLARIS__ */
|
||||
mo->ishelp = 1;
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
int res;
|
||||
#ifdef __SOLARIS__
|
||||
int pid;
|
||||
#endif /* __SOLARIS__ */
|
||||
|
||||
if (!mountpoint)
|
||||
return;
|
||||
@ -188,11 +381,214 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
|
||||
if (res == 1 && (pfd.revents & POLLERR))
|
||||
return;
|
||||
}
|
||||
#ifndef __SOLARIS__
|
||||
close(fd);
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
@ -213,14 +609,59 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
|
||||
struct mount_opts mo;
|
||||
int res = -1;
|
||||
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));
|
||||
#ifndef __SOLARIS__
|
||||
if (getuid())
|
||||
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 &&
|
||||
fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
|
||||
#ifndef __SOLARIS__
|
||||
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) {
|
||||
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;
|
||||
if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1)
|
||||
goto out;
|
||||
#ifndef __SOLARIS__
|
||||
if (!(mo.flags & MS_NODEV) && fuse_opt_add_opt(&mnt_opts, "dev") == -1)
|
||||
goto out;
|
||||
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;
|
||||
if (mo.fusermount_opts && fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) < 0)
|
||||
goto out;
|
||||
|
||||
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:
|
||||
free(mnt_opts);
|
||||
#ifdef __SOLARIS__
|
||||
fuse_opt_free_args(&sa);
|
||||
free(mo.subtype);
|
||||
free(mo.subtype_opt);
|
||||
#endif /* __SOLARIS__ */
|
||||
free(mo.fsname);
|
||||
free(mo.fusermount_opts);
|
||||
free(mo.kernel_opts);
|
||||
free(mo.mtab_opts);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,245 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __SOLARIS__
|
||||
#else /* __SOLARIS__ */
|
||||
#include <mntent.h>
|
||||
#include <sys/mount.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)
|
||||
{
|
||||
@ -217,3 +451,5 @@ int fuse_mnt_check_fuseblk(void)
|
||||
fclose(f);
|
||||
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);
|
||||
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,
|
||||
const char *origmnt);
|
||||
|
||||
#endif /* __SOLARIS__ */
|
||||
|
Loading…
Reference in New Issue
Block a user