kernel_interface.c (davfs2-1.6.1) | : | kernel_interface.c (davfs2-1.7.0) | ||
---|---|---|---|---|
/* kernel_interface.c. | /* kernel_interface.c. | |||
Copyright (C) 2006, 2007, 2008, 2009, 2014, 2020 Werner Baumann | Copyright (C) 2006, 2007, 2008, 2009, 2014, 2020 Werner Baumann | |||
Copyright (C) 2022 Ali Abdallah <ali.abdallah@suse.com> | ||||
This file is part of davfs2. | This file is part of davfs2. | |||
davfs2 is free software; you can redistribute it and/or modify | davfs2 is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 3 of the License, or | the Free Software Foundation; either version 3 of the License, or | |||
(at your option) any later version. | (at your option) any later version. | |||
davfs2 is distributed in the hope that it will be useful, | davfs2 is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | |||
along with davfs2; if not, write to the Free Software Foundation, | along with davfs2; if not, write to the Free Software Foundation, | |||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ | Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ | |||
#include "config.h" | #include "config.h" | |||
#include <errno.h> | ||||
#include <error.h> | ||||
#ifdef HAVE_FCNTL_H | #ifdef HAVE_FCNTL_H | |||
#include <fcntl.h> | #include <fcntl.h> | |||
#endif | #endif | |||
#ifdef HAVE_LIBINTL_H | #ifdef HAVE_LIBINTL_H | |||
#include <libintl.h> | #include <libintl.h> | |||
#endif | #endif | |||
#ifdef HAVE_STDDEF_H | #ifdef HAVE_STDDEF_H | |||
#include <stddef.h> | #include <stddef.h> | |||
#endif | #endif | |||
#ifdef HAVE_STDINT_H | #ifdef HAVE_STDINT_H | |||
skipping to change at line 50 | skipping to change at line 49 | |||
#include <string.h> | #include <string.h> | |||
#ifdef HAVE_SYSLOG_H | #ifdef HAVE_SYSLOG_H | |||
#include <syslog.h> | #include <syslog.h> | |||
#endif | #endif | |||
#ifdef HAVE_UNISTD_H | #ifdef HAVE_UNISTD_H | |||
#include <unistd.h> | #include <unistd.h> | |||
#endif | #endif | |||
#ifdef HAVE_SYS_MOUNT_H | #ifdef HAVE_SYS_MOUNT_H | |||
#include <sys/mount.h> | #include <sys/mount.h> | |||
#include <sys/uio.h> | ||||
#endif | #endif | |||
#ifdef HAVE_SYS_STAT_H | #ifdef HAVE_SYS_STAT_H | |||
#include <sys/stat.h> | #include <sys/stat.h> | |||
#endif | #endif | |||
#include <sys/wait.h> | #include <sys/wait.h> | |||
#include "util.h" | ||||
#include "defaults.h" | #include "defaults.h" | |||
#include "mount_davfs.h" | #include "mount_davfs.h" | |||
#include "cache.h" | #include "cache.h" | |||
#include "fuse_kernel.h" | #include "fuse_kernel.h" | |||
#include "kernel_interface.h" | #include "kernel_interface.h" | |||
#ifdef ENABLE_NLS | #ifdef ENABLE_NLS | |||
#define _(String) gettext(String) | #define _(String) gettext(String) | |||
#else | #else | |||
#define _(String) String | #define _(String) String | |||
#endif | #endif | |||
/* Private constants */ | /* Private constants */ | |||
/*===================*/ | /*===================*/ | |||
/* Name of the device to communicate with the kernel file system. */ | /* Name of the device to communicate with the kernel file system. */ | |||
#define FUSE_DEV_NAME "fuse" | #define FUSE_DEV_NAME "fuse" | |||
#ifdef __FreeBSD__ | ||||
enum { DAV_IOV_FSTYPE, DAV_IOV_ALLOW_OTHER, DAV_IOV_FSPATH, DAV_IOV_FSNAME, | ||||
DAV_IOV_FD, DAV_IOV_MAX_READ, DAV_IOV_ERR, DAV_IOV_MAX}; | ||||
/* max pairs of iovec mount options */ | ||||
#define DAV_MAX_IOVEC_LEN (DAV_IOV_MAX + 1) * 2 | ||||
/* Code taken from FreeBSD sbin/mount */ | ||||
static void | ||||
add_iovec_opt(struct iovec **iov, int *iovlen, const char *name, void *val, | ||||
size_t len) | ||||
{ | ||||
int i; | ||||
if (*iovlen < 0) | ||||
return; | ||||
i = *iovlen; | ||||
if (i + 2 > (DAV_MAX_IOVEC_LEN)) | ||||
{ | ||||
ERR("DAV_MAX_IOVEC_LEN reached\n"); | ||||
} | ||||
(*iov)[i].iov_base = strdup(name); | ||||
(*iov)[i].iov_len = strlen(name) + 1; | ||||
i++; | ||||
(*iov)[i].iov_base = val; | ||||
if (len == (size_t)-1) { | ||||
if (val != NULL) | ||||
len = strlen(val) + 1; | ||||
else | ||||
len = 0; | ||||
} | ||||
(*iov)[i].iov_len = (int)len; | ||||
*iovlen = ++i; | ||||
} | ||||
static void free_iovec (struct iovec *iov, int iovlen) | ||||
{ | ||||
int i = 0; | ||||
for (i = 0; i <= iovlen; i+=2) | ||||
{ | ||||
if (iov[i].iov_base) | ||||
free(iov[i].iov_base); | ||||
} | ||||
free(iov); | ||||
} | ||||
#endif | ||||
/* Public functions */ | /* Public functions */ | |||
/*==================*/ | /*==================*/ | |||
void | void | |||
dav_init_kernel_interface(int *dev, size_t *buf_size, const char *url, | dav_init_kernel_interface(int *dev, size_t *buf_size, const char *url, | |||
const char *mpoint, const dav_args *args) | const char *mpoint, const dav_args *args) | |||
{ | { | |||
#ifdef __FreeBSD__ | ||||
struct iovec *iov; | ||||
int iovlen; | ||||
char errmsg[255]; | ||||
char fdstr[15]; | ||||
char bufstr[15]; | ||||
iovlen = 0; | ||||
iov = NULL; | ||||
memset(errmsg, 0, sizeof(errmsg)); | ||||
#endif | ||||
uid_t orig = geteuid(); | uid_t orig = geteuid(); | |||
if (seteuid(0) != 0) | if (seteuid(0) != 0) | |||
error(EXIT_FAILURE, 0, _("can't change effective user id")); | ERR(_("can't change effective user id")); | |||
char *path; | char *path; | |||
if (asprintf(&path, "%s/%s", DAV_DEV_DIR, FUSE_DEV_NAME) < 0) | if (asprintf(&path, "%s/%s", DAV_DEV_DIR, FUSE_DEV_NAME) < 0) | |||
abort(); | abort(); | |||
*dev = open(path, O_RDWR | O_NONBLOCK); | *dev = open(path, O_RDWR | O_NONBLOCK); | |||
if (*dev <= 0) { | if (*dev <= 0) { | |||
error(0, 0, _("loading kernel module fuse")); | ERR(_("loading kernel module fuse")); | |||
int ret; | int ret; | |||
pid_t pid = fork(); | pid_t pid = fork(); | |||
if (pid == 0) { | if (pid == 0) { | |||
#if defined(__FreeBSD__) | ||||
execl("/sbin/kldload", "kldload", "fusefs", NULL); | ||||
#elif defined(__linux__) | ||||
execl("/sbin/modprobe", "modprobe", "fuse", NULL); | execl("/sbin/modprobe", "modprobe", "fuse", NULL); | |||
#endif | ||||
_exit(EXIT_FAILURE); | _exit(EXIT_FAILURE); | |||
} else if (pid < 0) { | } else if (pid < 0) { | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} else { | } else { | |||
if (waitpid(pid, &ret, 0) != pid) | if (waitpid(pid, &ret, 0) != pid) | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} | } | |||
if (ret) { | if (ret) { | |||
error(0, 0, _("loading kernel module fuse failed")); | WARN(_("loading kernel module fuse failed")); | |||
} else { | } else { | |||
*dev = open(path, O_RDWR | O_NONBLOCK); | *dev = open(path, O_RDWR | O_NONBLOCK); | |||
} | } | |||
if (*dev <= 0) { | if (*dev <= 0) { | |||
error(0, 0, _("waiting for /dev/fuse to be created")); | WARN(_("waiting for /dev/fuse to be created")); | |||
sleep(2); | sleep(2); | |||
*dev = open(path, O_RDWR | O_NONBLOCK); | *dev = open(path, O_RDWR | O_NONBLOCK); | |||
} | } | |||
} | } | |||
free(path); | free(path); | |||
if (*dev <= 0) { | if (*dev <= 0) { | |||
error(EXIT_FAILURE, 0, _("can't open fuse device")); | ERR(_("can't open fuse device")); | |||
} | } | |||
if (*buf_size < (FUSE_MIN_READ_BUFFER + 4096)) { | if (*buf_size < (FUSE_MIN_READ_BUFFER + 4096)) { | |||
*buf_size = FUSE_MIN_READ_BUFFER + 4096; | *buf_size = FUSE_MIN_READ_BUFFER + 4096; | |||
} | } | |||
#if defined(__FreeBSD__) | ||||
sprintf(fdstr, "%d", *dev); | ||||
sprintf(bufstr, "%lu", (unsigned long int) (*buf_size - 4096)); | ||||
int allow_other = 1; | ||||
iov = malloc (sizeof (struct iovec) * (DAV_MAX_IOVEC_LEN)); | ||||
add_iovec_opt(&iov, &iovlen, "fstype", __DECONST(void *, "fusefs"), (size_t) | ||||
-1); | ||||
add_iovec_opt(&iov, &iovlen, "allow_other", __DECONST(void *, &allow_other), | ||||
(size_t)-1); | ||||
add_iovec_opt(&iov, &iovlen, "fspath", __DECONST(void *, mpoint), (size_t)-1 | ||||
); | ||||
add_iovec_opt(&iov, &iovlen, "from", __DECONST(void *, "/dev/fuse"), (size_t | ||||
)-1); | ||||
add_iovec_opt(&iov, &iovlen, "fsname=", __DECONST(void *, url), strlen(url)+ | ||||
1); | ||||
add_iovec_opt(&iov, &iovlen, "fd", fdstr, (size_t)-1); | ||||
add_iovec_opt(&iov, &iovlen, "max_read=", bufstr, (ssize_t)-1); | ||||
add_iovec_opt(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); | ||||
if (nmount(iov, iovlen, args->mopts) == -1) { | ||||
if (*errmsg != '\0') | ||||
err(EXIT_FAILURE, _("mounting failed %s : %s"), url, errmsg); | ||||
else | ||||
err(EXIT_FAILURE, _("mounting failed %s"), url); | ||||
} | ||||
free_iovec(iov, iovlen); | ||||
#elif defined(__linux__) | ||||
char *mdata; | char *mdata; | |||
if (asprintf(&mdata, "fd=%i,rootmode=%o,user_id=%i,group_id=%i," | if (asprintf(&mdata, "fd=%i,rootmode=%o,user_id=%i,group_id=%i," | |||
"allow_other,max_read=%lu", *dev, args->dir_mode, args->uid, | "allow_other,max_read=%lu", *dev, args->dir_mode, args->uid, | |||
args->gid, (unsigned long int) (*buf_size - 4096)) < 0) | args->gid, (unsigned long int) (*buf_size - 4096)) < 0) | |||
abort(); | abort(); | |||
if (mount(url, mpoint, "fuse", args->mopts, mdata) != 0) { | if (mount(url, mpoint, "fuse", args->mopts, mdata) != 0) { | |||
error(EXIT_FAILURE, errno, _("mounting failed")); | ERR(_("mounting failed")); | |||
} | } | |||
free(mdata); | free(mdata); | |||
#endif | ||||
if (seteuid(orig) != 0) | if (seteuid(orig) != 0) | |||
error(EXIT_FAILURE, 0, _("can't change effective user id")); | ERR(_("can't change effective user id")); | |||
} | } | |||
End of changes. 17 change blocks. | ||||
9 lines changed or deleted | 114 lines changed or added |