[systemd-devel] [RFC] link against util-linux for fstab parsing
Dave Reisner
d at falconindy.com
Fri Feb 17 13:47:51 PST 2012
Based on the premise that we shouldn't develop a case of NIH, link
against a library whose sole purpose in life is parsing tab files.
---
Curious if something like this is wanted -- it's 90% complete, but there's no
sense in finishing it up if it's not interesting. I'd like to be able to get
rid of the fstab_node_to_udev_node() function but that would likely require
linking against libblkid in cryptsetup-generator.
Worth noting:
* in mount_fix_timeouts(), i've removed the possibility of using
'comment=systemd.device-timeout'. This option is undocumented in
systemd.mount(5), and util-linux will not parse out the value properly.
* is that this won't compile without util-linux from git or one of
the recent RCs as it depends on mnt_fs_is_swaparea().
Makefile.am | 6 ++-
configure.ac | 1 +
src/mount.c | 157 +++++++++++++++++++++++++++++-----------------------------
3 files changed, 83 insertions(+), 81 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 10c85a4..2559cde 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -493,7 +493,8 @@ libsystemd_core_la_CFLAGS = \
$(LIBWRAP_CFLAGS) \
$(PAM_CFLAGS) \
$(AUDIT_CFLAGS) \
- $(KMOD_CFLAGS)
+ $(KMOD_CFLAGS) \
+ $(MOUNT_CFLAGS)
libsystemd_core_la_LIBADD = \
libsystemd-basic.la \
@@ -503,7 +504,8 @@ libsystemd_core_la_LIBADD = \
$(PAM_LIBS) \
$(AUDIT_LIBS) \
$(CAP_LIBS) \
- $(KMOD_LIBS)
+ $(KMOD_LIBS) \
+ $(MOUNT_LIBS)
# This is needed because automake is buggy in how it generates the
# rules for C programs, but not Vala programs. We therefore can't
diff --git a/configure.ac b/configure.ac
index 62e8cdf..c8a8440 100644
--- a/configure.ac
+++ b/configure.ac
@@ -126,6 +126,7 @@ m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-conf
PKG_CHECK_MODULES(UDEV, [ libudev >= 172 ])
PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.3.2 ])
PKG_CHECK_MODULES(KMOD, [ libkmod >= 5 ])
+PKG_CHECK_MODULES(MOUNT, [ mount ])
have_selinux=no
AC_ARG_ENABLE(selinux, AS_HELP_STRING([--disable-selinux], [Disable optional SELINUX support]))
diff --git a/src/mount.c b/src/mount.c
index 5e52a54..cc675d4 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -25,6 +25,8 @@
#include <sys/epoll.h>
#include <signal.h>
+#include <libmount/libmount.h>
+
#include "unit.h"
#include "mount.h"
#include "load-fragment.h"
@@ -262,27 +264,10 @@ static int mount_add_socket_links(Mount *m) {
return 0;
}
-static char* mount_test_option(const char *haystack, const char *needle) {
- struct mntent me;
-
- assert(needle);
-
- /* Like glibc's hasmntopt(), but works on a string, not a
- * struct mntent */
-
- if (!haystack)
- return false;
-
- zero(me);
- me.mnt_opts = (char*) haystack;
-
- return hasmntopt(&me, needle);
-}
-
static bool mount_is_network(MountParameters *p) {
assert(p);
- if (mount_test_option(p->options, "_netdev"))
+ if (mnt_match_options(p->options, "_netdev"))
return true;
if (p->fstype && fstype_is_network(p->fstype))
@@ -294,7 +279,7 @@ static bool mount_is_network(MountParameters *p) {
static bool mount_is_bind(MountParameters *p) {
assert(p);
- if (mount_test_option(p->options, "bind"))
+ if (mnt_match_options(p->options, "bind"))
return true;
if (p->fstype && streq(p->fstype, "bind"))
@@ -312,11 +297,11 @@ static bool needs_quota(MountParameters *p) {
if (mount_is_bind(p))
return false;
- return mount_test_option(p->options, "usrquota") ||
- mount_test_option(p->options, "grpquota") ||
- mount_test_option(p->options, "quota") ||
- mount_test_option(p->options, "usrjquota") ||
- mount_test_option(p->options, "grpjquota");
+ return mnt_match_options(p->options, "usrquota") ||
+ mnt_match_options(p->options, "grpquota") ||
+ mnt_match_options(p->options, "quota") ||
+ mnt_match_options(p->options, "usrjquota") ||
+ mnt_match_options(p->options, "grpjquota");
}
static int mount_add_fstab_links(Mount *m) {
@@ -337,15 +322,15 @@ static int mount_add_fstab_links(Mount *m) {
if (p != &m->parameters_etc_fstab)
return 0;
- noauto = !!mount_test_option(p->options, "noauto");
- nofail = !!mount_test_option(p->options, "nofail");
+ noauto = mnt_match_options(p->options, "+noauto");
+ nofail = mnt_match_options(p->options, "+nofail");
automount =
- mount_test_option(p->options, "comment=systemd.automount") ||
- mount_test_option(p->options, "x-systemd-automount");
+ mnt_match_options(p->options, "comment=systemd.automount") ||
+ mnt_match_options(p->options, "x-systemd-automount");
handle =
automount ||
- mount_test_option(p->options, "comment=systemd.mount") ||
- mount_test_option(p->options, "x-systemd-mount") ||
+ mnt_match_options(p->options, "comment=systemd.mount") ||
+ mnt_match_options(p->options, "x-systemd-mount") ||
UNIT(m)->manager->mount_auto;
if (mount_is_network(p)) {
@@ -421,8 +406,8 @@ static int mount_add_device_links(Mount *m) {
p == &m->parameters_etc_fstab) {
bool nofail, noauto;
- noauto = !!mount_test_option(p->options, "noauto");
- nofail = !!mount_test_option(p->options, "nofail");
+ noauto = mnt_match_options(p->options, "+noauto");
+ nofail = mnt_match_options(p->options, "+nofail");
if ((r = unit_add_node_link(UNIT(m), p->what,
!noauto && nofail &&
@@ -485,6 +470,8 @@ static int mount_add_default_dependencies(Mount *m) {
static int mount_fix_timeouts(Mount *m) {
MountParameters *p;
const char *timeout = NULL;
+ char *opt;
+ size_t optsz;
Unit *other;
Iterator i;
usec_t u;
@@ -501,14 +488,10 @@ static int mount_fix_timeouts(Mount *m) {
* endless device timeouts for devices that show up only after
* user input, like crypto devices. */
- if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
- timeout += 31;
- else if ((timeout = mount_test_option(p->options, "x-systemd-device-timeout")))
- timeout += 25;
- else
+ if (mnt_optstr_get_option(p->options, "x-systemd-device-timeout", &opt, &optsz) != 0)
return 0;
- t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
+ t = strndup(timeout, optsz);
if (!t)
return -ENOMEM;
@@ -1505,86 +1488,102 @@ fail:
return r;
}
-static int mount_find_pri(char *options) {
- char *end, *pri;
+static int mount_find_pri(const char *options) {
+ char *opt, *end;
+ char buf[32];
+ size_t optsz;
unsigned long r;
- if (!(pri = mount_test_option(options, "pri")))
+ if (mnt_optstr_get_option(options, "pri", &opt, &optsz) != 0)
return 0;
- pri += 4;
+ if (optsz + 1 > sizeof(buf))
+ optsz = sizeof(buf);
+
+ snprintf(buf, optsz + 1, "%s", opt);
errno = 0;
- r = strtoul(pri, &end, 10);
+ r = strtoul(buf, &end, 10);
if (errno != 0)
return -errno;
- if (end == pri || (*end != ',' && *end != 0))
+ if (end == buf || (*end != '\0'))
return -EINVAL;
return (int) r;
}
static int mount_load_etc_fstab(Manager *m) {
- FILE *f;
+ struct libmnt_table *tb = NULL;
+ struct libmnt_cache *mnt_cache = NULL;
+ struct libmnt_iter *itr = NULL;
+ struct libmnt_fs *fs = NULL;
int r = 0;
- struct mntent* me;
-
- assert(m);
- errno = 0;
- if (!(f = setmntent("/etc/fstab", "r")))
- return -errno;
+ tb = mnt_new_table();
+ if (!tb) {
+ return -ENOMEM;
+ }
- while ((me = getmntent(f))) {
- char *where, *what;
- int k;
+ mnt_cache = mnt_new_cache();
+ if (!mnt_cache) {
+ r = -ENOMEM;
+ goto finish;
+ }
- if (!(what = fstab_node_to_udev_node(me->mnt_fsname))) {
- r = -ENOMEM;
- goto finish;
- }
+ mnt_table_set_cache(tb, mnt_cache);
- if (!(where = strdup(me->mnt_dir))) {
- free(what);
- r = -ENOMEM;
- goto finish;
- }
+ r = mnt_table_parse_fstab(tb, "/etc/fstab");
+ if (r != 0)
+ goto finish;
- if (what[0] == '/')
- path_kill_slashes(what);
+ itr = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!itr) {
+ r = -ENOMEM;
+ goto finish;
+ }
- if (where[0] == '/')
- path_kill_slashes(where);
+ while (mnt_table_next_fs(tb, itr, &fs) == 0) {
+ int k;
+ const char *opts = mnt_fs_get_options(fs);
- if (streq(me->mnt_type, "swap")) {
- int pri;
+ if (mnt_fs_is_swaparea(fs)) {
+ int pri = mount_find_pri(opts);
- if ((pri = mount_find_pri(me->mnt_opts)) < 0)
+ if (pri < 0)
k = pri;
else
k = swap_add_one(m,
- what,
+ mnt_fs_get_source(fs),
NULL,
pri,
- !!mount_test_option(me->mnt_opts, "noauto"),
- !!mount_test_option(me->mnt_opts, "nofail"),
- !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
+ mnt_fs_match_options(fs, "+noauto"),
+ mnt_fs_match_options(fs, "+nofail"),
+ mnt_fs_match_options(fs, "comment=systemd.swapon"),
false);
} else
- k = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, me->mnt_passno, false, false);
-
- free(what);
- free(where);
+ k = mount_add_one(m,
+ mnt_fs_get_source(fs),
+ mnt_fs_get_target(fs),
+ opts,
+ mnt_fs_get_fstype(fs),
+ mnt_fs_get_passno(fs),
+ false,
+ false);
if (k < 0)
r = k;
}
+ mnt_free_iter(itr);
+
finish:
+ if (tb)
+ mnt_free_table(tb);
+ if (mnt_cache)
+ mnt_free_cache(mnt_cache);
- endmntent(f);
return r;
}
--
1.7.9.1
More information about the systemd-devel
mailing list