Use utab if mtab is a symbolic link

This commit is contained in:
wbaumann
2014-04-05 18:27:36 +00:00
parent 77d51ac385
commit 2b1f99b123
13 changed files with 711 additions and 551 deletions

View File

@ -37,6 +37,7 @@ AM_CFLAGS = -Wall -Werror=format-security \
-fstack-protector --param=ssp-buffer-size=4
DEFS = -DPROGRAM_NAME=\"mount.davfs\" \
-DDAV_SYS_CONF_DIR=\"$(pkgsysconfdir)\" \
-DDAV_LOCALSTATE_DIR=\"$(dav_localstatedir)\" \
-DDAV_SYS_RUN=\"$(pkglocalstatedir)\" \
-DDAV_SYS_CACHE=\"$(pkgsyscachedir)\" \
-DDAV_SECRETS=\"secrets\" \

View File

@ -28,10 +28,15 @@
/* These Macros will be defined by the command line option -D of the
preprocessor:
The name of the program.
The name of the program, usually mount.davfs.
DPROGRAM_NAME
The directory to store the PID-file.
The system directory that holds runtime status information, usually
/var/run or /run.
DAV_LOCALSTATE_DIR
The directory to store the PID-file, usually /var/run/mount.davfs
or /run/mount.davfs.
DAV_SYS_RUN
The directory for translated messages (gettext).
@ -45,13 +50,15 @@
/* These Macros will be defined by the command line option -D of the
preprocessor:
The directory where the system wide configuration file is located.
The directory where the system wide configuration file is located,
usually either /etc/davfs2 or /urs/local/etc/davfs2.
DAV_SYS_CONF_DIR
The name of the configuration file.
The name of the configuration file, usually davfs2.conf.
DAV_CONFIG
The directory where the template of the configuration file is located.
The directory where the template of the configuration file is located
usually either /usr/share/davfs2 or /usr/local/share/davfs2.
DAV_DATA_DIR
*/
@ -63,11 +70,11 @@
/* These Macros will be defined by the command line option -D of the
preprocessor:
The program will run as this user if invoked by root.
The program will run as this user if invoked by root, usually davfs2.
May be overridden by system config file.
DAV_USER
The program will belong to this group.
The program will belong to this group, usually davfs2.
May be overridden by system config file.
DAV_GROUP
*/
@ -79,6 +86,20 @@
/* File system type to be used with 'mount -t' and fstab. */
#define DAV_FS_TYPE "davfs"
/* If _PATH_MOUNTED (the mtab file) is a symbolic link (to /proc/mounts)
some information required for umount is missing (e.g. the option
user=<name of the mounting user|) and in the case of davfs2 the file
system type will not be davfs but that of the kernel file system
(fuse or coda). Newer versions of the mount program will store this
information in the utab-file /var/run/mount/utab or /run/mount/utab.
davfs2 will do the same. */
/* The subdirectory of DAV_LOCALSTATE_DIR where the utab-file is placed. */
#define DAV_UTAB_DIR "mount"
/* The name of the utab-file. */
#define DAV_UTAB "utab"
/* The file davfs reads mtab entries from. If not available it will
use _PATH_MOUNTED. */
#define DAV_MOUNTS "/proc/mounts"

View File

@ -59,6 +59,9 @@
#include <unistd.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
@ -455,14 +458,36 @@ check_dirs(dav_args *args)
struct stat st;
char *fname;
if (lstat(_PATH_MOUNTED, &st) != 0)
error(EXIT_FAILURE, errno, _("can't access file %s"), _PATH_MOUNTED);
int mtab_is_link = S_ISLNK(st.st_mode);
if (stat(DAV_MOUNTS, &st) == 0) {
mounts = DAV_MOUNTS;
args->use_utab = mtab_is_link;
} else {
mounts = _PATH_MOUNTED;
}
if (debug)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "mounts in: %s", mounts);
if (!args->use_utab) {
char *utab_dir = xasprintf("%s/%s", DAV_LOCALSTATE_DIR, DAV_UTAB_DIR);
if (stat(utab_dir, &st) != 0) {
gain_privileges(args);
if (mkdir(utab_dir, S_IRWXU | S_IRGRP | S_IXGRP
| S_IROTH | S_IXOTH) != 0) {
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " and %s/%s",
utab_dir, DAV_UTAB);
}else {
error(0, errno, _("can't create directory %s"),
utab_dir);
}
release_privileges(args);
}
free(utab_dir);
}
gain_privileges(args);
if (stat(DAV_SYS_RUN, &st) != 0) {
if (mkdir(DAV_SYS_RUN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_ISVTX)
@ -1171,42 +1196,101 @@ termination_handler(int signo)
/* Adds an entry to _PATH_MOUNTED for the mounted file system.
If _PATH_MOUNTED is a symbolic link to /proc/mounts it will write an
entry into /var/run/mount/utab instead.
If this fails a warning will be printed, but this will not stop mounting. */
static void
write_mtab_entry(const dav_args *args)
{
struct mntent mntent;
mntent.mnt_fsname = url;
mntent.mnt_dir = mpoint;
mntent.mnt_type = DAV_FS_TYPE;
mntent.mnt_opts = xasprintf("%s%s%s%s%s%s",
(args->mopts & MS_RDONLY) ? "ro" : "rw",
(args->mopts & MS_NOSUID) ? ",nosuid" : "",
(args->mopts & MS_NOEXEC) ? ",noexec" : "",
(args->mopts & MS_NODEV) ? ",nodev" : "",
(args->netdev) ? ",_netdev" : "",
(args->add_mopts != NULL) ? args->add_mopts : "");
mntent. mnt_freq = 0;
mntent. mnt_passno = 0;
mntent.mnt_opts = NULL;
char *utab_line = NULL;
char *tab_file = NULL;
char *lock_file = NULL;
if (!args->privileged) {
char *opts = mntent.mnt_opts;
mntent.mnt_opts = xasprintf("%s,user=%s", opts, args->uid_name);
free(opts);
if (args->use_utab) {
utab_line = xasprintf("SRC=%s TARGET=%s ROOT=/ OPTS=%s%s%shelper=%s\n",
url, mpoint,
(!args->privileged) ? "user=" : "",
(!args->privileged) ? args->uid_name : "",
(!args->privileged) ? "," : "",
DAV_FS_TYPE);
tab_file = xasprintf("%s/%s/%s", DAV_LOCALSTATE_DIR, DAV_UTAB_DIR,
DAV_UTAB);
lock_file = xasprintf("%s,lock", tab_file);
} else {
mntent.mnt_fsname = url;
mntent.mnt_dir = mpoint;
mntent.mnt_type = DAV_FS_TYPE;
mntent.mnt_opts = xasprintf("%s%s%s%s%s%s%s%s",
(args->mopts & MS_RDONLY) ? "ro" : "rw",
(args->mopts & MS_NOSUID) ? ",nosuid" : "",
(args->mopts & MS_NOEXEC) ? ",noexec" : "",
(args->mopts & MS_NODEV) ? ",nodev" : "",
(args->netdev) ? ",_netdev" : "",
(args->add_mopts != NULL) ? args->add_mopts : "",
(!args->privileged) ? ",user=" : "",
(!args->privileged) ? args->uid_name : "");
mntent. mnt_freq = 0;
mntent. mnt_passno = 0;
tab_file = xstrdup(_PATH_MOUNTED);
lock_file = xasprintf("%s~", tab_file);
}
sigset_t oldset;
sigemptyset(&oldset);
sigset_t newset;
sigfillset(&newset);
sigprocmask(SIG_BLOCK, &newset, &oldset);
gain_privileges(args);
FILE *mtab = setmntent(_PATH_MOUNTED, "a");
if (mtab) {
addmntent(mtab, &mntent);
endmntent(mtab);
} else {
error(0, 0, _("Warning: can't write entry into mtab, but will mount "
"the file system anyway"));
int ld = open(lock_file, O_RDONLY | O_CREAT,
S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
if (!ld)
error(EXIT_FAILURE, errno, _("can't create file %s"), lock_file);
while (flock(ld, LOCK_EX) != 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
error(EXIT_FAILURE, errno, _("can't lock file %s"), lock_file);
}
FILE *tab = NULL;
if (args->use_utab) {
tab = fopen(tab_file, "a");
} else {
tab = setmntent(tab_file, "a");
}
int err = 0;
if (tab) {
if (args->use_utab) {
if (fputs(utab_line, tab) == EOF)
err = 1;
fclose(tab);
} else {
if (addmntent(tab, &mntent) != 0)
err = 1;
endmntent(tab);
}
}
if (!tab || err)
error(0, 0, _("Warning: can't write entry into %s, but will mount "
"the file system anyway"), tab_file);
close(ld);
remove(lock_file);
release_privileges(args);
free(mntent.mnt_opts);
sigprocmask(SIG_SETMASK, &oldset, NULL);
if (lock_file)
free(lock_file);
if (tab_file)
free(tab_file);
if (utab_line)
free(utab_line);
if (mntent.mnt_opts)
free(mntent.mnt_opts);
}

View File

@ -52,6 +52,7 @@ typedef struct {
int netdev; /* Command line */
unsigned long int mopts; /* Command line */
char *add_mopts;
int use_utab;
size_t buf_size; /* User config file, system config file */
/* File mode */
uid_t fsuid; /* Command line */

View File

@ -128,7 +128,7 @@ main(int argc, char *argv[])
if (!mpoint)
mpoint = argv[optind];
if (!mpoint || *mpoint != '/')
error(EXIT_FAILURE, 0, _("can't determine mount point"));
error(EXIT_FAILURE, errno, _("can't determine mount point"));
char *m = mpoint;
while (*m == '/')