mirror of
https://github.com/libfuse/libfuse.git
synced 2026-07-07 14:47:41 +08:00
Merge branch 'master' into fuse-service-container
* master: Change use_subtype_prefix type to bool in fuse_mnt_build_source() lib mount: fix fsfd leakage on error lib mount: include linux/mount.h in mount_i_linux.h lib mount: no need to fsconfig mtab options Fix ENODEV fallback logic for block devices with fsname Update the condition when to use synchronous init fuse_daemonize_early: Rename is_active to is_used, add new is_active Add a missing NULL check for x_mtab_opts in mount_fuse() fusermount: Fix heap buffer overflow in perform_mount() lib/mount.c: Restore "subtype#fsname" format for legacy kernel fallback fuse: No need to call strlen
This commit is contained in:
@@ -2438,9 +2438,13 @@ int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf);
|
||||
* called after this if io-uring is enabled. Also see
|
||||
* fuse_session_daemonize_start().
|
||||
*
|
||||
* @param se the session
|
||||
* @param enable disable auto-detection based on fuse_daemonize_early_start,
|
||||
* true to forcefully enable, false to forcefully disable
|
||||
*
|
||||
* This must be called before fuse_session_mount() to have any effect.
|
||||
*/
|
||||
void fuse_session_want_sync_init(struct fuse_session *se);
|
||||
void fuse_session_set_sync_init(struct fuse_session *se, bool enable);
|
||||
|
||||
/**
|
||||
* Check if the connection / session is using synchronous FUSE_INIT
|
||||
|
||||
+4
-3
@@ -2685,11 +2685,12 @@ static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
|
||||
struct node *dot = NULL;
|
||||
|
||||
if (name[0] == '.') {
|
||||
int len = strlen(name);
|
||||
bool isdot = (name[1] == '\0');
|
||||
bool isdotdot = ((name[1] == '.') && (name[2] == '\0'));
|
||||
|
||||
if (len == 1 || (name[1] == '.' && len == 2)) {
|
||||
if (isdot || isdotdot) {
|
||||
pthread_mutex_lock(&f->lock);
|
||||
if (len == 1) {
|
||||
if (isdot) {
|
||||
if (f->conf.debug)
|
||||
fuse_log(FUSE_LOG_DEBUG, "LOOKUP-DOT\n");
|
||||
dot = get_node_nocheck(f, parent);
|
||||
|
||||
@@ -287,7 +287,7 @@ void fuse_daemonize_early_success(void)
|
||||
* Needs to be gracefully handled as automatically called libfuse
|
||||
* internal from FUSE_INIT handler
|
||||
*/
|
||||
if (!fuse_daemonize_early_is_active())
|
||||
if (!fuse_daemonize_early_is_used())
|
||||
return;
|
||||
|
||||
fuse_daemonize_early_signal(FUSE_DAEMONIZE_SUCCESS);
|
||||
@@ -298,11 +298,16 @@ void fuse_daemonize_early_fail(int err)
|
||||
fuse_daemonize_early_signal(err);
|
||||
}
|
||||
|
||||
bool fuse_daemonize_early_is_active(void)
|
||||
bool fuse_daemonize_early_is_used(void)
|
||||
{
|
||||
return daemonize.daemonized || daemonize.active;
|
||||
}
|
||||
|
||||
bool fuse_daemonize_early_is_active(void)
|
||||
{
|
||||
return daemonize.active;
|
||||
}
|
||||
|
||||
void fuse_daemonize_early_set_mounted(void)
|
||||
{
|
||||
daemonize.mounted = true;
|
||||
@@ -322,7 +327,7 @@ int fuse_daemonize(int foreground);
|
||||
int fuse_daemonize(int foreground)
|
||||
{
|
||||
/* Check if the NEW API is used */
|
||||
if (fuse_daemonize_early_is_active()) {
|
||||
if (fuse_daemonize_early_is_used()) {
|
||||
perror("Newer API fuse_daemonize_start() already used\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -389,8 +394,4 @@ int fuse_daemonize(int foreground)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool fuse_daemonize_is_used(void)
|
||||
{
|
||||
return daemonize.active;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
*/
|
||||
void fuse_daemonize_early_set_mounted(void);
|
||||
|
||||
/*
|
||||
* Check if daemonization is used.
|
||||
*
|
||||
* @return true if used, false otherwise
|
||||
/**
|
||||
* Check if fuse_daemonize_early_start() was used
|
||||
*/
|
||||
bool fuse_daemonize_is_used(void);
|
||||
bool fuse_daemonize_early_is_used(void);
|
||||
|
||||
/* Set on handling FUSE_INIT */
|
||||
void fuse_daemonize_set_got_init(void);
|
||||
|
||||
+7
-1
@@ -72,6 +72,12 @@ struct fuse_session_uring {
|
||||
|
||||
struct fuse_timeout_thread;
|
||||
|
||||
enum fuse_sync_init {
|
||||
FUSE_SYNC_INIT_AUTO = 0, /* auto detection using fuse_daemonize_early_start */
|
||||
FUSE_SYNC_INIT_DISABLED, /* sync init forcefully disabled */
|
||||
FUSE_SYNC_INIT_ENABLED /* sync_init forcefully enabled */
|
||||
};
|
||||
|
||||
struct fuse_session {
|
||||
_Atomic(char *)mountpoint;
|
||||
int fd;
|
||||
@@ -111,7 +117,7 @@ struct fuse_session {
|
||||
bool buf_reallocable;
|
||||
|
||||
/* synchronous FUSE_INIT support */
|
||||
bool want_sync_init;
|
||||
enum fuse_sync_init want_sync_init;
|
||||
bool is_sync_init; /* sync FUSE_INIT mount succeeded*/
|
||||
pthread_t init_thread;
|
||||
int init_error;
|
||||
|
||||
+9
-3
@@ -4325,6 +4325,8 @@ fuse_session_new_versioned(struct fuse_args *args,
|
||||
|
||||
se->mo = mo;
|
||||
|
||||
se->want_sync_init = FUSE_SYNC_INIT_AUTO;
|
||||
|
||||
/* Fuse server application should pass the version it was compiled
|
||||
* against and pass it. If a libfuse version accidentally introduces an
|
||||
* ABI incompatibility, it might be possible to 'fix' that at run time,
|
||||
@@ -4497,7 +4499,9 @@ static int session_start_sync_init(struct fuse_session *se, int fd,
|
||||
* Older fuse servers do not set want_sync_init or start the new
|
||||
* daemonize code, so they get async init.
|
||||
*/
|
||||
if (!fuse_daemonize_is_used() || !se->want_sync_init) {
|
||||
if (se->want_sync_init == FUSE_SYNC_INIT_DISABLED ||
|
||||
(se->want_sync_init == FUSE_SYNC_INIT_AUTO &&
|
||||
!fuse_daemonize_early_is_used())) {
|
||||
if (se->debug)
|
||||
fuse_log(FUSE_LOG_DEBUG,
|
||||
"fuse: sync init not enabled\n");
|
||||
@@ -5121,11 +5125,13 @@ void fuse_session_stop_teardown_watchdog(void *data)
|
||||
fuse_tt_destruct(tt);
|
||||
}
|
||||
|
||||
void fuse_session_want_sync_init(struct fuse_session *se)
|
||||
void fuse_session_set_sync_init(struct fuse_session *se, bool enable)
|
||||
{
|
||||
if (se == NULL)
|
||||
return;
|
||||
se->want_sync_init = true;
|
||||
|
||||
se->want_sync_init = enable ? FUSE_SYNC_INIT_ENABLED :
|
||||
FUSE_SYNC_INIT_DISABLED;
|
||||
}
|
||||
|
||||
void fuse_session_set_debug(struct fuse_session *se)
|
||||
|
||||
+1
-1
@@ -992,7 +992,7 @@ int fuse_service_session_mount(struct fuse_service *sf, struct fuse_session *se,
|
||||
{
|
||||
char *fstype = fuse_mnt_build_type(se->mo->blkdev, se->mo->subtype);
|
||||
char *source = fuse_mnt_build_source(se->mo->fsname, se->mo->subtype,
|
||||
fuse_mnt_get_devname());
|
||||
fuse_mnt_get_devname(), false);
|
||||
char *mntopts = fuse_mnt_kernel_opts(se->mo);
|
||||
char *mtabopts = fuse_mnt_mtab_opts(se->mo);
|
||||
char path[32];
|
||||
|
||||
@@ -232,6 +232,7 @@ FUSE_3.19 {
|
||||
fuse_daemonize_early_fail;
|
||||
fuse_daemonize_early_is_active;
|
||||
fuse_session_set_debug;
|
||||
fuse_session_set_sync_init;
|
||||
fuse_service_accept;
|
||||
fuse_service_append_args;
|
||||
fuse_service_can_allow_other;
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_daemonize.h"
|
||||
#include "fuse_daemonize_i.h"
|
||||
#include "fuse_service.h"
|
||||
#include "mount_util.h"
|
||||
|
||||
@@ -447,7 +448,7 @@ int fuse_main_real_versioned(int argc, char *argv[],
|
||||
}
|
||||
|
||||
/* The application might have already started daemonization itself */
|
||||
if (!fuse_daemonize_early_is_active()) {
|
||||
if (!fuse_daemonize_early_is_used()) {
|
||||
int daemonize_early_flags = 0;
|
||||
|
||||
if (opts.foreground)
|
||||
|
||||
+12
-7
@@ -659,7 +659,7 @@ int fuse_kern_do_mount(const char *mnt, struct mount_opts *mo,
|
||||
int res;
|
||||
const char *devname = fuse_mnt_get_devname();
|
||||
res = -ENOMEM;
|
||||
source = fuse_mnt_build_source(mo->fsname, mo->subtype, devname);
|
||||
source = fuse_mnt_build_source(mo->fsname, mo->subtype, devname, 0);
|
||||
type = fuse_mnt_build_type(mo->blkdev, mo->subtype);
|
||||
if (!type || !source) {
|
||||
fuse_log(FUSE_LOG_ERR, "%s: failed to allocate memory\n",
|
||||
@@ -670,16 +670,21 @@ int fuse_kern_do_mount(const char *mnt, struct mount_opts *mo,
|
||||
res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
|
||||
if (res == -1 && errno == ENODEV && mo->subtype) {
|
||||
/* Probably missing subtype support */
|
||||
|
||||
/*
|
||||
* The allocated space by fuse_mnt_build_{source,type}
|
||||
* might be too small.
|
||||
*/
|
||||
free(source);
|
||||
free(type);
|
||||
|
||||
type = fuse_mnt_build_type(mo->blkdev, NULL);
|
||||
source = fuse_mnt_build_source(mo->fsname, NULL, devname);
|
||||
if (mo->fsname) {
|
||||
if (!mo->blkdev) {
|
||||
source = fuse_mnt_build_source(mo->fsname, mo->subtype,
|
||||
devname, 1);
|
||||
} else {
|
||||
source = fuse_mnt_build_source(mo->fsname, NULL,
|
||||
devname, 0);
|
||||
}
|
||||
} else {
|
||||
source = strdup(type);
|
||||
}
|
||||
|
||||
if (!type || !source) {
|
||||
fuse_log(FUSE_LOG_ERR,
|
||||
|
||||
+3
-14
@@ -309,7 +309,7 @@ int fuse_kern_fsmount(const char *mnt, unsigned long flags, int blkdev,
|
||||
|
||||
/* Build type and source strings */
|
||||
type = fuse_mnt_build_type(blkdev, subtype);
|
||||
source = fuse_mnt_build_source(fsname, subtype, source_dev);
|
||||
source = fuse_mnt_build_source(fsname, subtype, source_dev, 0);
|
||||
err = -ENOMEM;
|
||||
if (!type || !source) {
|
||||
fprintf(stderr, "fuse: failed to allocate memory\n");
|
||||
@@ -363,16 +363,6 @@ int fuse_kern_fsmount(const char *mnt, unsigned long flags, int blkdev,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Apply mtab options (overlap with kernel_opts is filtered and tolerated) */
|
||||
err = apply_fsconfig_mount_opts(fsfd, mtab_opts);
|
||||
if (err < 0) {
|
||||
log_fsconfig_kmsg(fsfd);
|
||||
fprintf(stderr,
|
||||
"fuse: failed to apply mtab options '%s'\n",
|
||||
mtab_opts);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Create the filesystem instance */
|
||||
res = fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
|
||||
if (res == -1) {
|
||||
@@ -387,9 +377,8 @@ int fuse_kern_fsmount(const char *mnt, unsigned long flags, int blkdev,
|
||||
flags = ms_flags_to_mount_attrs(flags, &mount_attrs);
|
||||
if (flags != 0) {
|
||||
/* unsupported flags found, either fsconfig or mount attr flags */
|
||||
//fuse_log(FUSE_LOG_ERR, "Unsupported mount flags found: %d", flags);
|
||||
errno = -ENOTSUP;
|
||||
return -1;
|
||||
errno = ENOTSUP;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Create mount object with mount attributes */
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define FUSE_MOUNT_I_LINUX_H_
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <linux/mount.h>
|
||||
|
||||
struct fuse_args;
|
||||
|
||||
|
||||
+15
-3
@@ -536,13 +536,25 @@ const char *fuse_mnt_get_devname(void)
|
||||
}
|
||||
|
||||
char *fuse_mnt_build_source(const char *fsname, const char *subtype,
|
||||
const char *devname)
|
||||
const char *devname, bool use_subtype_prefix)
|
||||
{
|
||||
char *source;
|
||||
int ret;
|
||||
|
||||
ret = asprintf(&source, "%s",
|
||||
fsname ? fsname : (subtype ? subtype : devname));
|
||||
if (use_subtype_prefix && fsname && subtype) {
|
||||
ret = asprintf(&source, "%s#%s", subtype, fsname);
|
||||
} else {
|
||||
const char *src_str;
|
||||
|
||||
if (fsname)
|
||||
src_str = fsname;
|
||||
else if (subtype)
|
||||
src_str = subtype;
|
||||
else
|
||||
src_str = devname;
|
||||
ret = asprintf(&source, "%s", src_str);
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
return NULL;
|
||||
|
||||
|
||||
+14
-2
@@ -10,6 +10,7 @@
|
||||
#define FUSE_MOUNT_UTIL_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include "mount_common_i.h" // IWYU pragma: keep
|
||||
|
||||
/* Mount flags mapping structure */
|
||||
@@ -37,9 +38,20 @@ const char *fuse_mnt_get_devname(void);
|
||||
int fuse_mnt_add_mount_helper(const char *mnt, const char *source,
|
||||
const char *type, const char *mtab_opts);
|
||||
|
||||
/* Build source and type strings for mounting */
|
||||
/*
|
||||
* Build the mount source string for FUSE filesystems
|
||||
* @fsname: Filesystem name (e.g., "user@host:/path")
|
||||
* @subtype: Filesystem subtype (e.g., "sshfs")
|
||||
* @devname: Device name (typically "/dev/fuse")
|
||||
* @use_subtype_prefix: Set to 1 when falling back from a failed mount attempt
|
||||
* with fuse.subtype (ENODEV error), to retry with the
|
||||
* legacy "subtype#fsname" format. Set to 0 for the initial
|
||||
* mount attempt on modern kernels.
|
||||
*
|
||||
* Returns: Allocated source string, or NULL on error
|
||||
*/
|
||||
char *fuse_mnt_build_source(const char *fsname, const char *subtype,
|
||||
const char *devname);
|
||||
const char *devname, bool use_subtype_prefix);
|
||||
char *fuse_mnt_build_type(int blkdev, const char *subtype);
|
||||
|
||||
#endif /* FUSE_MOUNT_UTIL_H_ */
|
||||
|
||||
@@ -168,3 +168,75 @@ def test_mountinfo_attrs_root(tmpdir, output_checker, name,
|
||||
with hello_mount(tmpdir, output_checker, name, opts) as mnt:
|
||||
info = parse_mountinfo(mnt)
|
||||
_check_attrs(info, must_have, must_not_have)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name', ('hello', 'hello_ll'))
|
||||
def test_mountinfo_blkdev_with_fsname(tmpdir, output_checker, name):
|
||||
"""
|
||||
Test block device mount with fsname and subtype.
|
||||
|
||||
This test validates the ENODEV fallback logic for block devices with fsname.
|
||||
When mounting with blkdev=1, fsname=<device>, and subtype=mysub, the mount
|
||||
source should be the device name (fsname), not the filesystem type string.
|
||||
|
||||
The ENODEV fallback has three cases:
|
||||
1. fsname + non-blkdev -> "subtype#fsname" (legacy format for regular FUSE)
|
||||
2. fsname + blkdev -> fsname only (THIS TEST - for block devices)
|
||||
3. no fsname -> type string
|
||||
|
||||
This test catches a regression where the logic was incorrectly simplified
|
||||
from nested conditionals to a single combined condition (fsname && !blkdev),
|
||||
causing case 2 to fall through to case 3 and use 'fuseblk' instead of the
|
||||
device name.
|
||||
|
||||
Requires root to create loop devices; skipped otherwise.
|
||||
"""
|
||||
if os.getuid() != 0:
|
||||
pytest.skip('blkdev option requires root')
|
||||
|
||||
import tempfile
|
||||
|
||||
# Create a file to use as a loop device
|
||||
with tempfile.NamedTemporaryFile(mode='wb', delete=False,
|
||||
dir=str(tmpdir)) as f:
|
||||
loop_file = f.name
|
||||
# Create a 1MB file
|
||||
f.write(b'\0' * (1024 * 1024))
|
||||
|
||||
try:
|
||||
# Create loop device from file
|
||||
result = subprocess.run(['losetup', '-f', '--show', loop_file],
|
||||
capture_output=True, text=True, check=True)
|
||||
loop_dev = result.stdout.strip()
|
||||
|
||||
try:
|
||||
# Mount with blkdev, fsname, and subtype
|
||||
# The fsname should be the loop device
|
||||
with hello_mount(tmpdir.mkdir('mnt'), output_checker, name,
|
||||
('blkdev', f'fsname={loop_dev}', 'subtype=mysub')) as mnt:
|
||||
info = parse_mountinfo(mnt)
|
||||
|
||||
assert info is not None, 'mountpoint not found in /proc/self/mountinfo'
|
||||
|
||||
# For block devices, fstype should be 'fuseblk' or 'fuseblk.mysub'
|
||||
# depending on whether the kernel supports the subtype
|
||||
assert info['fstype'] in ('fuseblk', 'fuseblk.mysub'), \
|
||||
f"unexpected fstype for blkdev: {info['fstype']}"
|
||||
|
||||
# CRITICAL: Source should be the loop device name (fsname), NOT 'fuseblk'
|
||||
# This is what the fix ensures - before the fix, it would be 'fuseblk'
|
||||
# because the incorrect condition treated (fsname && blkdev) as (no fsname)
|
||||
assert info['source'] == loop_dev, \
|
||||
f"blkdev source should be fsname ({loop_dev}), got {info['source']}"
|
||||
|
||||
finally:
|
||||
# Detach loop device
|
||||
subprocess.run(['losetup', '-d', loop_dev], check=False)
|
||||
|
||||
finally:
|
||||
# Clean up file
|
||||
try:
|
||||
os.unlink(loop_file)
|
||||
except OSError:
|
||||
# Ignore cleanup errors - file may already be deleted or inaccessible
|
||||
pass
|
||||
|
||||
+61
-27
@@ -678,10 +678,6 @@ struct mount_params {
|
||||
char *subtype; /* Subtype from options */
|
||||
int blkdev; /* Block device flag */
|
||||
|
||||
/* Generated mount parameters */
|
||||
char *source; /* Mount source string */
|
||||
char *type; /* Filesystem type string */
|
||||
|
||||
/* mtab/utab record content: MS_* flag mirrors + kernel-bound -o opts
|
||||
* + user=<n> (non-root)
|
||||
*/
|
||||
@@ -696,8 +692,6 @@ static void free_mount_params(struct mount_params *mp)
|
||||
free(mp->optbuf);
|
||||
free(mp->fsname);
|
||||
free(mp->subtype);
|
||||
free(mp->source);
|
||||
free(mp->type);
|
||||
free(mp->mtab_opts);
|
||||
memset(mp, 0, sizeof(*mp));
|
||||
}
|
||||
@@ -821,13 +815,6 @@ static int prepare_mount(const char *opts, struct mount_params *mp)
|
||||
sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
|
||||
mp->fd, mp->rootmode, getuid(), getgid());
|
||||
|
||||
mp->source = fuse_mnt_build_source(mp->fsname, mp->subtype, mp->dev);
|
||||
mp->type = fuse_mnt_build_type(mp->blkdev, mp->subtype);
|
||||
if (!mp->type || !mp->source) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -837,31 +824,60 @@ err:
|
||||
|
||||
/*
|
||||
* Perform the actual mount operation using prepared parameters.
|
||||
* Builds source and type strings and returns them via output parameters.
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int perform_mount(const char *mnt, struct mount_params *mp)
|
||||
static int perform_mount(const char *mnt, struct mount_params *mp,
|
||||
char **source_out, char **type_out)
|
||||
{
|
||||
int res;
|
||||
char *source = NULL;
|
||||
char *type = NULL;
|
||||
|
||||
res = mount_notrunc(mp->source, mnt, mp->type, mp->flags, mp->optbuf);
|
||||
source = fuse_mnt_build_source(mp->fsname, mp->subtype, mp->dev, 0);
|
||||
type = fuse_mnt_build_type(mp->blkdev, mp->subtype);
|
||||
if (!type || !source) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
free(source);
|
||||
free(type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mount_notrunc(source, mnt, type, mp->flags, mp->optbuf);
|
||||
if (res == -1 && errno == ENODEV && mp->subtype) {
|
||||
/* Probably missing subtype support */
|
||||
strcpy(mp->type, mp->blkdev ? "fuseblk" : "fuse");
|
||||
free(source);
|
||||
free(type);
|
||||
|
||||
type = fuse_mnt_build_type(mp->blkdev, NULL);
|
||||
if (mp->fsname) {
|
||||
if (!mp->blkdev)
|
||||
sprintf(mp->source, "%s#%s", mp->subtype, mp->fsname);
|
||||
if (!mp->blkdev) {
|
||||
source = fuse_mnt_build_source(mp->fsname,
|
||||
mp->subtype,
|
||||
mp->dev, 1);
|
||||
} else {
|
||||
source = fuse_mnt_build_source(mp->fsname, NULL,
|
||||
mp->dev, 0);
|
||||
}
|
||||
} else {
|
||||
strcpy(mp->source, mp->type);
|
||||
source = strdup(type);
|
||||
}
|
||||
|
||||
res = mount_notrunc(mp->source, mnt, mp->type, mp->flags, mp->optbuf);
|
||||
if (!type || !source) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
free(source);
|
||||
free(type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mount_notrunc(source, mnt, type, mp->flags, mp->optbuf);
|
||||
}
|
||||
if (res == -1 && errno == EINVAL) {
|
||||
/* It could be an old version not supporting group_id */
|
||||
sprintf(mp->optbuf_end, "fd=%i,rootmode=%o,user_id=%u",
|
||||
mp->fd, mp->rootmode, getuid());
|
||||
res = mount_notrunc(mp->source, mnt, mp->type, mp->flags, mp->optbuf);
|
||||
res = mount_notrunc(source, mnt, type, mp->flags, mp->optbuf);
|
||||
}
|
||||
if (res == -1) {
|
||||
int errno_save = errno;
|
||||
@@ -871,9 +887,13 @@ static int perform_mount(const char *mnt, struct mount_params *mp)
|
||||
else
|
||||
fprintf(stderr, "%s: mount failed: %s\n", progname,
|
||||
strerror(errno_save));
|
||||
free(source);
|
||||
free(type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*source_out = source;
|
||||
*type_out = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -883,6 +903,8 @@ static int do_mount(const char *mnt, const char **typep, mode_t rootmode,
|
||||
{
|
||||
struct mount_params mp = { .fd = fd }; /* implicit zero of other params */
|
||||
int res;
|
||||
char *source = NULL;
|
||||
char *type = NULL;
|
||||
|
||||
mp.rootmode = rootmode;
|
||||
mp.dev = dev;
|
||||
@@ -891,14 +913,14 @@ static int do_mount(const char *mnt, const char **typep, mode_t rootmode,
|
||||
if (res == -1)
|
||||
return -1;
|
||||
|
||||
res = perform_mount(mnt, &mp);
|
||||
res = perform_mount(mnt, &mp, &source, &type);
|
||||
if (res == -1) {
|
||||
free_mount_params(&mp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*sourcep = mp.source;
|
||||
*typep = mp.type;
|
||||
*sourcep = source;
|
||||
*typep = type;
|
||||
*mtab_optsp = mp.mtab_opts;
|
||||
|
||||
/* Free only the intermediate allocations, not the returned ones */
|
||||
@@ -1133,10 +1155,16 @@ static int mount_fuse_finish_fsmount(const char *mnt,
|
||||
goto fail_free_merged;
|
||||
}
|
||||
|
||||
/* Store results in context */
|
||||
ctx->source = mp.source;
|
||||
/* Build source and type for mtab after successful mount */
|
||||
ctx->source = fuse_mnt_build_source(mp.fsname, mp.subtype, ctx->dev, 0);
|
||||
*type = fuse_mnt_build_type(mp.blkdev, mp.subtype);
|
||||
if (!*type || !ctx->source) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
goto fail_free_merged;
|
||||
}
|
||||
|
||||
/* Store mtab_opts in context */
|
||||
ctx->mtab_opts = final_mtab_opts;
|
||||
*type = mp.type;
|
||||
|
||||
res = 0;
|
||||
|
||||
@@ -1218,6 +1246,12 @@ static int mount_fuse(const char *mnt, const char *opts, const char **type)
|
||||
size_t x_mtab_opts_len = mtab_opts_len +
|
||||
strlen(x_prefixed_opts) + 2;
|
||||
char *x_mtab_opts = calloc(1, x_mtab_opts_len);
|
||||
if (x_mtab_opts == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: failed to allocate memory for mtab_opts\n",
|
||||
progname);
|
||||
goto fail_close_fd;
|
||||
}
|
||||
|
||||
if (mtab_opts_len) {
|
||||
strcpy(x_mtab_opts, mtab_opts);
|
||||
|
||||
Reference in New Issue
Block a user