summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO70
-rw-r--r--0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch3277
-rw-r--r--60-rfkill.rules1
-rw-r--r--PKGBUILD185
-rw-r--r--pam-common6
-rw-r--r--pam-login7
-rw-r--r--pam-runuser4
-rw-r--r--pam-su9
-rw-r--r--util-linux.sysusers3
9 files changed, 3562 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 00000000000..7bd544b7b96
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,70 @@
+pkgbase = util-linux-nosystemd-minimal-git
+ pkgdesc = Miscellaneous system utilities for Linux
+ pkgver = 2.36.1
+ pkgrel = 1
+ url = https://www.kernel.org/pub/linux/utils/util-linux
+ arch = x86_64
+ license = GPL2
+ makedepends = python
+ makedepends = libcap-ng
+ makedepends = libxcrypt
+ options = strip
+ source = git+https://github.com/karelzak/util-linux.git
+ source = pam-login
+ source = pam-common
+ source = pam-runuser
+ source = pam-su
+ source = 60-rfkill.rules
+ source = util-linux.sysusers
+ source = 0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+ sha256sums = SKIP
+
+pkgname = util-linux-nosystemd-minimal-git
+ groups = base
+ groups = base-devel
+ depends = pam
+ depends = shadow
+ depends = coreutils
+ depends = libutil-linux
+ depends = libeudev
+ depends = libcap-ng
+ depends = libxcrypt
+ depends = libcrypt.so
+ depends = libmagic.so
+ depends = libncursesw.so
+ depends = libreadline.so
+ optdepends = python: python bindings to libmount
+ optdepends = words: default dictionary for look
+ provides = rfkill
+ provides = util-linux
+ conflicts = rfkill
+ conflicts = util-linux
+ replaces = rfkill
+ backup = etc/pam.d/chfn
+ backup = etc/pam.d/chsh
+ backup = etc/pam.d/login
+ backup = etc/pam.d/runuser
+ backup = etc/pam.d/runuser-l
+ backup = etc/pam.d/su
+ backup = etc/pam.d/su-l
+
+pkgname = util-linux-libs-nosystemd-minimal-git
+ pkgdesc = util-linux runtime libraries
+ provides = util-linux-libs
+ provides = libutil-linux
+ provides = libblkid.so
+ provides = libfdisk.so
+ provides = libmount.so
+ provides = libsmartcols.so
+ provides = libuuid.so
+ conflicts = libutil-linux
+ conflicts = util-linux-libs
+ replaces = libutil-linux
+
diff --git a/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch b/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch
new file mode 100644
index 00000000000..a4377ece4df
--- /dev/null
+++ b/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch
@@ -0,0 +1,3277 @@
+diff -Nuar -uar a/libmount/src/context_mount.c b/libmount/src/context_mount.c
+--- a/libmount/src/context_mount.c 2020-11-13 22:00:15.000000000 +1100
++++ b/libmount/src/context_mount.c 2020-12-21 12:32:20.836075130 +1100
+@@ -38,37 +38,37 @@
+ */
+ struct libmnt_addmount *mnt_new_addmount(void)
+ {
+- struct libmnt_addmount *ad = calloc(1, sizeof(*ad));
+- if (!ad)
+- return NULL;
++ struct libmnt_addmount *ad = calloc(1, sizeof(*ad));
++ if (!ad)
++ return NULL;
+
+- INIT_LIST_HEAD(&ad->mounts);
+- return ad;
++ INIT_LIST_HEAD(&ad->mounts);
++ return ad;
+ }
+
+ void mnt_free_addmount(struct libmnt_addmount *ad)
+ {
+- if (!ad)
+- return;
+- list_del(&ad->mounts);
+- free(ad);
++ if (!ad)
++ return;
++ list_del(&ad->mounts);
++ free(ad);
+ }
+
+ static int mnt_context_append_additional_mount(struct libmnt_context *cxt,
+- struct libmnt_addmount *ad)
++ struct libmnt_addmount *ad)
+ {
+- assert(cxt);
+- assert(ad);
++ assert(cxt);
++ assert(ad);
+
+- if (!list_empty(&ad->mounts))
+- return -EINVAL;
++ if (!list_empty(&ad->mounts))
++ return -EINVAL;
+
+- DBG(CXT, ul_debugobj(cxt,
+- "mount: add additional flag: 0x%08lx",
+- ad->mountflags));
++ DBG(CXT, ul_debugobj(cxt,
++ "mount: add additional flag: 0x%08lx",
++ ad->mountflags));
+
+- list_add_tail(&ad->mounts, &cxt->addmounts);
+- return 0;
++ list_add_tail(&ad->mounts, &cxt->addmounts);
++ return 0;
+ }
+
+ /*
+@@ -77,60 +77,60 @@
+ */
+ static int init_propagation(struct libmnt_context *cxt)
+ {
+- char *name;
+- char *opts = (char *) mnt_fs_get_vfs_options(cxt->fs);
+- size_t namesz;
+- struct libmnt_optmap const *maps[1];
+- int rec_count = 0;
++ char *name;
++ char *opts = (char *) mnt_fs_get_vfs_options(cxt->fs);
++ size_t namesz;
++ struct libmnt_optmap const *maps[1];
++ int rec_count = 0;
+
+- if (!opts)
+- return 0;
++ if (!opts)
++ return 0;
+
+- DBG(CXT, ul_debugobj(cxt, "mount: initialize additional propagation mounts"));
++ DBG(CXT, ul_debugobj(cxt, "mount: initialize additional propagation mounts"));
+
+- maps[0] = mnt_get_builtin_optmap(MNT_LINUX_MAP);
++ maps[0] = mnt_get_builtin_optmap(MNT_LINUX_MAP);
+
+- while (!mnt_optstr_next_option(&opts, &name, &namesz, NULL, NULL)) {
+- const struct libmnt_optmap *ent;
+- struct libmnt_addmount *ad;
+- int rc;
++ while (!mnt_optstr_next_option(&opts, &name, &namesz, NULL, NULL)) {
++ const struct libmnt_optmap *ent;
++ struct libmnt_addmount *ad;
++ int rc;
+
+- if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent) || !ent)
+- continue;
++ if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent) || !ent)
++ continue;
+
+- DBG(CXT, ul_debugobj(cxt, " checking %s", ent->name));
++ DBG(CXT, ul_debugobj(cxt, " checking %s", ent->name));
+
+- /* Note that MS_REC may be used for more flags, so we have to keep
+- * track about number of recursive options to keep the MS_REC in the
+- * mountflags if necessary.
+- */
+- if (ent->id & MS_REC)
+- rec_count++;
++ /* Note that MS_REC may be used for more flags, so we have to keep
++ * track about number of recursive options to keep the MS_REC in the
++ * mountflags if necessary.
++ */
++ if (ent->id & MS_REC)
++ rec_count++;
+
+- if (!(ent->id & MS_PROPAGATION))
+- continue;
++ if (!(ent->id & MS_PROPAGATION))
++ continue;
+
+- ad = mnt_new_addmount();
+- if (!ad)
+- return -ENOMEM;
++ ad = mnt_new_addmount();
++ if (!ad)
++ return -ENOMEM;
+
+- ad->mountflags = ent->id;
+- DBG(CXT, ul_debugobj(cxt, " adding extra mount(2) call for %s", ent->name));
+- rc = mnt_context_append_additional_mount(cxt, ad);
+- if (rc)
+- return rc;
++ ad->mountflags = ent->id;
++ DBG(CXT, ul_debugobj(cxt, " adding extra mount(2) call for %s", ent->name));
++ rc = mnt_context_append_additional_mount(cxt, ad);
++ if (rc)
++ return rc;
+
+- DBG(CXT, ul_debugobj(cxt, " removing %s from primary mount(2) call", ent->name));
+- cxt->mountflags &= ~ent->id;
++ DBG(CXT, ul_debugobj(cxt, " removing %s from primary mount(2) call", ent->name));
++ cxt->mountflags &= ~ent->id;
+
+- if (ent->id & MS_REC)
+- rec_count--;
+- }
++ if (ent->id & MS_REC)
++ rec_count--;
++ }
+
+- if (rec_count)
+- cxt->mountflags |= MS_REC;
++ if (rec_count)
++ cxt->mountflags |= MS_REC;
+
+- return 0;
++ return 0;
+ }
+
+ /*
+@@ -139,50 +139,50 @@
+ */
+ static int init_bind_remount(struct libmnt_context *cxt)
+ {
+- struct libmnt_addmount *ad;
+- int rc;
++ struct libmnt_addmount *ad;
++ int rc;
+
+- assert(cxt);
+- assert(cxt->mountflags & MS_BIND);
+- assert(!(cxt->mountflags & MS_REMOUNT));
++ assert(cxt);
++ assert(cxt->mountflags & MS_BIND);
++ assert(!(cxt->mountflags & MS_REMOUNT));
+
+- DBG(CXT, ul_debugobj(cxt, "mount: initialize additional ro,bind mount"));
++ DBG(CXT, ul_debugobj(cxt, "mount: initialize additional ro,bind mount"));
+
+- ad = mnt_new_addmount();
+- if (!ad)
+- return -ENOMEM;
++ ad = mnt_new_addmount();
++ if (!ad)
++ return -ENOMEM;
+
+- ad->mountflags = cxt->mountflags;
+- ad->mountflags |= (MS_REMOUNT | MS_BIND);
++ ad->mountflags = cxt->mountflags;
++ ad->mountflags |= (MS_REMOUNT | MS_BIND);
+
+- rc = mnt_context_append_additional_mount(cxt, ad);
+- if (rc)
+- return rc;
++ rc = mnt_context_append_additional_mount(cxt, ad);
++ if (rc)
++ return rc;
+
+- return 0;
++ return 0;
+ }
+
+ #if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK)
+ struct libmnt_optname {
+- const char *name;
+- size_t namesz;
++ const char *name;
++ size_t namesz;
+ };
+
+-#define DEF_OPTNAME(n) { .name = n, .namesz = sizeof(n) - 1 }
+-#define DEF_OPTNAME_LAST { .name = NULL }
++#define DEF_OPTNAME(n) { .name = n, .namesz = sizeof(n) - 1 }
++#define DEF_OPTNAME_LAST { .name = NULL }
+
+ static int is_option(const char *name, size_t namesz,
+- const struct libmnt_optname *names)
++ const struct libmnt_optname *names)
+ {
+- const struct libmnt_optname *p;
++ const struct libmnt_optname *p;
+
+- for (p = names; p && p->name; p++) {
+- if (p->namesz == namesz
+- && strncmp(name, p->name, namesz) == 0)
+- return 1;
+- }
++ for (p = names; p && p->name; p++) {
++ if (p->namesz == namesz
++ && strncmp(name, p->name, namesz) == 0)
++ return 1;
++ }
+
+- return 0;
++ return 0;
+ }
+ #endif /* HAVE_LIBSELINUX || HAVE_SMACK */
+
+@@ -191,194 +191,194 @@
+ */
+ static int fix_optstr(struct libmnt_context *cxt)
+ {
+- int rc = 0;
+- struct libmnt_ns *ns_old;
+- char *next;
+- char *name, *val;
+- size_t namesz, valsz;
+- struct libmnt_fs *fs;
++ int rc = 0;
++ struct libmnt_ns *ns_old;
++ char *next;
++ char *name, *val;
++ size_t namesz, valsz;
++ struct libmnt_fs *fs;
+ #ifdef HAVE_LIBSELINUX
+- int se_fix = 0, se_rem = 0;
+- static const struct libmnt_optname selinux_options[] = {
+- DEF_OPTNAME("context"),
+- DEF_OPTNAME("fscontext"),
+- DEF_OPTNAME("defcontext"),
+- DEF_OPTNAME("rootcontext"),
+- DEF_OPTNAME("seclabel"),
+- DEF_OPTNAME_LAST
+- };
++ int se_fix = 0, se_rem = 0;
++ static const struct libmnt_optname selinux_options[] = {
++ DEF_OPTNAME("context"),
++ DEF_OPTNAME("fscontext"),
++ DEF_OPTNAME("defcontext"),
++ DEF_OPTNAME("rootcontext"),
++ DEF_OPTNAME("seclabel"),
++ DEF_OPTNAME_LAST
++ };
+ #endif
+ #ifdef HAVE_SMACK
+- int sm_rem = 0;
+- static const struct libmnt_optname smack_options[] = {
+- DEF_OPTNAME("smackfsdef"),
+- DEF_OPTNAME("smackfsfloor"),
+- DEF_OPTNAME("smackfshat"),
+- DEF_OPTNAME("smackfsroot"),
+- DEF_OPTNAME("smackfstransmute"),
+- DEF_OPTNAME_LAST
+- };
++ int sm_rem = 0;
++ static const struct libmnt_optname smack_options[] = {
++ DEF_OPTNAME("smackfsdef"),
++ DEF_OPTNAME("smackfsfloor"),
++ DEF_OPTNAME("smackfshat"),
++ DEF_OPTNAME("smackfsroot"),
++ DEF_OPTNAME("smackfstransmute"),
++ DEF_OPTNAME_LAST
++ };
+ #endif
+- assert(cxt);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++ assert(cxt);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+
+- if (!cxt->fs || (cxt->flags & MNT_FL_MOUNTOPTS_FIXED))
+- return 0;
++ if (!cxt->fs || (cxt->flags & MNT_FL_MOUNTOPTS_FIXED))
++ return 0;
+
+- fs = cxt->fs;
++ fs = cxt->fs;
+
+- DBG(CXT, ul_debugobj(cxt, "mount: fixing options, current "
+- "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'",
+- fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr));
+-
+- /*
+- * The "user" options is our business (so we can modify the option),
+- * the exception is command line for /sbin/mount.<type> helpers. Let's
+- * save the original user=<name> to call the helpers with an unchanged
+- * "user" setting.
+- */
+- if (cxt->user_mountflags & MNT_MS_USER) {
+- if (!mnt_optstr_get_option(fs->user_optstr,
+- "user", &val, &valsz) && val) {
+- cxt->orig_user = strndup(val, valsz);
+- if (!cxt->orig_user) {
+- rc = -ENOMEM;
+- goto done;
+- }
+- }
+- cxt->flags |= MNT_FL_SAVED_USER;
+- }
+-
+- /*
+- * Sync mount options with mount flags
+- */
+- DBG(CXT, ul_debugobj(cxt, "mount: fixing vfs optstr"));
+- rc = mnt_optstr_apply_flags(&fs->vfs_optstr, cxt->mountflags,
+- mnt_get_builtin_optmap(MNT_LINUX_MAP));
+- if (rc)
+- goto done;
+-
+- DBG(CXT, ul_debugobj(cxt, "mount: fixing user optstr"));
+- rc = mnt_optstr_apply_flags(&fs->user_optstr, cxt->user_mountflags,
+- mnt_get_builtin_optmap(MNT_USERSPACE_MAP));
+- if (rc)
+- goto done;
+-
+- if (fs->vfs_optstr && *fs->vfs_optstr == '\0') {
+- free(fs->vfs_optstr);
+- fs->vfs_optstr = NULL;
+- }
+- if (fs->user_optstr && *fs->user_optstr == '\0') {
+- free(fs->user_optstr);
+- fs->user_optstr = NULL;
+- }
+- if (cxt->mountflags & MS_PROPAGATION) {
+- rc = init_propagation(cxt);
+- if (rc)
+- return rc;
+- }
+- if ((cxt->mountflags & MS_BIND)
+- && (cxt->mountflags & MNT_BIND_SETTABLE)
+- && !(cxt->mountflags & MS_REMOUNT)) {
+- rc = init_bind_remount(cxt);
+- if (rc)
+- return rc;
+- }
++ DBG(CXT, ul_debugobj(cxt, "mount: fixing options, current "
++ "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'",
++ fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr));
++
++ /*
++ * The "user" options is our business (so we can modify the option),
++ * the exception is command line for /sbin/mount.<type> helpers. Let's
++ * save the original user=<name> to call the helpers with an unchanged
++ * "user" setting.
++ */
++ if (cxt->user_mountflags & MNT_MS_USER) {
++ if (!mnt_optstr_get_option(fs->user_optstr,
++ "user", &val, &valsz) && val) {
++ cxt->orig_user = strndup(val, valsz);
++ if (!cxt->orig_user) {
++ rc = -ENOMEM;
++ goto done;
++ }
++ }
++ cxt->flags |= MNT_FL_SAVED_USER;
++ }
++
++ /*
++ * Sync mount options with mount flags
++ */
++ DBG(CXT, ul_debugobj(cxt, "mount: fixing vfs optstr"));
++ rc = mnt_optstr_apply_flags(&fs->vfs_optstr, cxt->mountflags,
++ mnt_get_builtin_optmap(MNT_LINUX_MAP));
++ if (rc)
++ goto done;
++
++ DBG(CXT, ul_debugobj(cxt, "mount: fixing user optstr"));
++ rc = mnt_optstr_apply_flags(&fs->user_optstr, cxt->user_mountflags,
++ mnt_get_builtin_optmap(MNT_USERSPACE_MAP));
++ if (rc)
++ goto done;
++
++ if (fs->vfs_optstr && *fs->vfs_optstr == '\0') {
++ free(fs->vfs_optstr);
++ fs->vfs_optstr = NULL;
++ }
++ if (fs->user_optstr && *fs->user_optstr == '\0') {
++ free(fs->user_optstr);
++ fs->user_optstr = NULL;
++ }
++ if (cxt->mountflags & MS_PROPAGATION) {
++ rc = init_propagation(cxt);
++ if (rc)
++ return rc;
++ }
++ if ((cxt->mountflags & MS_BIND)
++ && (cxt->mountflags & MNT_BIND_SETTABLE)
++ && !(cxt->mountflags & MS_REMOUNT)) {
++ rc = init_bind_remount(cxt);
++ if (rc)
++ return rc;
++ }
+
+- next = fs->fs_optstr;
++ next = fs->fs_optstr;
+
+ #ifdef HAVE_LIBSELINUX
+- if (!is_selinux_enabled())
+- /* Always remove SELinux garbage if SELinux disabled */
+- se_rem = 1;
+- else if (cxt->mountflags & MS_REMOUNT)
+- /*
+- * Linux kernel < 2.6.39 does not support remount operation
+- * with any selinux specific mount options.
+- *
+- * Kernel 2.6.39 commits: ff36fe2c845cab2102e4826c1ffa0a6ebf487c65
+- * 026eb167ae77244458fa4b4b9fc171209c079ba7
+- * fix this odd behavior, so we don't have to care about it in
+- * userspace.
+- */
+- se_rem = get_linux_version() < KERNEL_VERSION(2, 6, 39);
+- else
+- /* For normal mount, contexts are translated */
+- se_fix = 1;
+-
+- if (!se_rem) {
+- /* de-duplicate SELinux options */
+- const struct libmnt_optname *p;
+- for (p = selinux_options; p && p->name; p++)
+- mnt_optstr_deduplicate_option(&fs->fs_optstr, p->name);
+- }
++ if (!is_selinux_enabled())
++ /* Always remove SELinux garbage if SELinux disabled */
++ se_rem = 1;
++ else if (cxt->mountflags & MS_REMOUNT)
++ /*
++ * Linux kernel < 2.6.39 does not support remount operation
++ * with any selinux specific mount options.
++ *
++ * Kernel 2.6.39 commits: ff36fe2c845cab2102e4826c1ffa0a6ebf487c65
++ * 026eb167ae77244458fa4b4b9fc171209c079ba7
++ * fix this odd behavior, so we don't have to care about it in
++ * userspace.
++ */
++ se_rem = get_linux_version() < KERNEL_VERSION(2, 6, 39);
++ else
++ /* For normal mount, contexts are translated */
++ se_fix = 1;
++
++ if (!se_rem) {
++ /* de-duplicate SELinux options */
++ const struct libmnt_optname *p;
++ for (p = selinux_options; p && p->name; p++)
++ mnt_optstr_deduplicate_option(&fs->fs_optstr, p->name);
++ }
+ #endif
+ #ifdef HAVE_SMACK
+- if (access("/sys/fs/smackfs", F_OK) != 0)
+- sm_rem = 1;
++ if (access("/sys/fs/smackfs", F_OK) != 0)
++ sm_rem = 1;
+ #endif
+- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
++ while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
+
+- if (namesz == 3 && !strncmp(name, "uid", 3))
+- rc = mnt_optstr_fix_uid(&fs->fs_optstr, val, valsz, &next);
+- else if (namesz == 3 && !strncmp(name, "gid", 3))
+- rc = mnt_optstr_fix_gid(&fs->fs_optstr, val, valsz, &next);
++ if (namesz == 3 && !strncmp(name, "uid", 3))
++ rc = mnt_optstr_fix_uid(&fs->fs_optstr, val, valsz, &next);
++ else if (namesz == 3 && !strncmp(name, "gid", 3))
++ rc = mnt_optstr_fix_gid(&fs->fs_optstr, val, valsz, &next);
+ #ifdef HAVE_LIBSELINUX
+- else if ((se_rem || se_fix)
+- && is_option(name, namesz, selinux_options)) {
++ else if ((se_rem || se_fix)
++ && is_option(name, namesz, selinux_options)) {
+
+- if (se_rem) {
+- /* remove context= option */
+- next = name;
+- rc = mnt_optstr_remove_option_at(&fs->fs_optstr,
+- name,
+- val ? val + valsz :
+- name + namesz);
+- } else if (se_fix && val && valsz)
+- /* translate selinux contexts */
+- rc = mnt_optstr_fix_secontext(&fs->fs_optstr,
+- val, valsz, &next);
+- }
++ if (se_rem) {
++ /* remove context= option */
++ next = name;
++ rc = mnt_optstr_remove_option_at(&fs->fs_optstr,
++ name,
++ val ? val + valsz :
++ name + namesz);
++ } else if (se_fix && val && valsz)
++ /* translate selinux contexts */
++ rc = mnt_optstr_fix_secontext(&fs->fs_optstr,
++ val, valsz, &next);
++ }
+ #endif
+ #ifdef HAVE_SMACK
+- else if (sm_rem && is_option(name, namesz, smack_options)) {
++ else if (sm_rem && is_option(name, namesz, smack_options)) {
+
+- next = name;
+- rc = mnt_optstr_remove_option_at(&fs->fs_optstr,
+- name,
+- val ? val + valsz : name + namesz);
+- }
++ next = name;
++ rc = mnt_optstr_remove_option_at(&fs->fs_optstr,
++ name,
++ val ? val + valsz : name + namesz);
++ }
+ #endif
+- if (rc)
+- goto done;
+- }
+-
+-
+- if (!rc && mnt_context_is_restricted(cxt) && (cxt->user_mountflags & MNT_MS_USER)) {
+- ns_old = mnt_context_switch_origin_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
+-
+- rc = mnt_optstr_fix_user(&fs->user_optstr);
+-
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
+- }
+-
+- /* refresh merged optstr */
+- free(fs->optstr);
+- fs->optstr = NULL;
+- fs->optstr = mnt_fs_strdup_options(fs);
++ if (rc)
++ goto done;
++ }
++
++
++ if (!rc && mnt_context_is_restricted(cxt) && (cxt->user_mountflags & MNT_MS_USER)) {
++ ns_old = mnt_context_switch_origin_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
++
++ rc = mnt_optstr_fix_user(&fs->user_optstr);
++
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
++ }
++
++ /* refresh merged optstr */
++ free(fs->optstr);
++ fs->optstr = NULL;
++ fs->optstr = mnt_fs_strdup_options(fs);
+ done:
+- cxt->flags |= MNT_FL_MOUNTOPTS_FIXED;
++ cxt->flags |= MNT_FL_MOUNTOPTS_FIXED;
+
+- DBG(CXT, ul_debugobj(cxt, "fixed options [rc=%d]: "
+- "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", rc,
+- fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr));
+-
+- if (rc)
+- rc = -MNT_ERR_MOUNTOPT;
+- return rc;
++ DBG(CXT, ul_debugobj(cxt, "fixed options [rc=%d]: "
++ "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", rc,
++ fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr));
++
++ if (rc)
++ rc = -MNT_ERR_MOUNTOPT;
++ return rc;
+ }
+
+ /*
+@@ -387,74 +387,74 @@
+ */
+ static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr)
+ {
+- struct libmnt_optmap const *maps[2];
+- char *next, *name, *val;
+- size_t namesz, valsz;
+- int rc = 0;
+-
+- assert(cxt);
+- assert(cxt->fs);
+- assert(optstr);
+-
+- DBG(CXT, ul_debugobj(cxt, "mount: generate helper mount options"));
+-
+- *optstr = mnt_fs_strdup_options(cxt->fs);
+- if (!*optstr)
+- return -ENOMEM;
+-
+- if ((cxt->user_mountflags & MNT_MS_USER) ||
+- (cxt->user_mountflags & MNT_MS_USERS)) {
+- /*
+- * This is unnecessary for real user-mounts as mount.<type>
+- * helpers always have to follow fstab rather than mount
+- * options on the command line.
+- *
+- * However, if you call mount.<type> as root, then the helper follows
+- * the command line. If there is (for example) "user,exec" in fstab,
+- * then we have to manually append the "exec" back to the options
+- * string, because there is nothing like MS_EXEC (we only have
+- * MS_NOEXEC in mount flags and we don't care about the original
+- * mount string in libmount for VFS options).
+- */
+- if (!(cxt->mountflags & MS_NOEXEC))
+- mnt_optstr_append_option(optstr, "exec", NULL);
+- if (!(cxt->mountflags & MS_NOSUID))
+- mnt_optstr_append_option(optstr, "suid", NULL);
+- if (!(cxt->mountflags & MS_NODEV))
+- mnt_optstr_append_option(optstr, "dev", NULL);
+- if (!(cxt->mountflags & MS_NOSYMFOLLOW))
+- mnt_optstr_append_option(optstr, "symfollow", NULL);
+- }
+-
+-
+- if (cxt->flags & MNT_FL_SAVED_USER)
+- rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user);
+- if (rc)
+- goto err;
+-
+- /* remove userspace options with MNT_NOHLPS flag */
+- maps[0] = mnt_get_builtin_optmap(MNT_USERSPACE_MAP);
+- maps[1] = mnt_get_builtin_optmap(MNT_LINUX_MAP);
+- next = *optstr;
+-
+- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
+- const struct libmnt_optmap *ent;
+-
+- mnt_optmap_get_entry(maps, 2, name, namesz, &ent);
+- if (ent && ent->id && (ent->mask & MNT_NOHLPS)) {
+- next = name;
+- rc = mnt_optstr_remove_option_at(optstr, name,
+- val ? val + valsz : name + namesz);
+- if (rc)
+- goto err;
+- }
+- }
++ struct libmnt_optmap const *maps[2];
++ char *next, *name, *val;
++ size_t namesz, valsz;
++ int rc = 0;
++
++ assert(cxt);
++ assert(cxt->fs);
++ assert(optstr);
++
++ DBG(CXT, ul_debugobj(cxt, "mount: generate helper mount options"));
++
++ *optstr = mnt_fs_strdup_options(cxt->fs);
++ if (!*optstr)
++ return -ENOMEM;
++
++ if ((cxt->user_mountflags & MNT_MS_USER) ||
++ (cxt->user_mountflags & MNT_MS_USERS)) {
++ /*
++ * This is unnecessary for real user-mounts as mount.<type>
++ * helpers always have to follow fstab rather than mount
++ * options on the command line.
++ *
++ * However, if you call mount.<type> as root, then the helper follows
++ * the command line. If there is (for example) "user,exec" in fstab,
++ * then we have to manually append the "exec" back to the options
++ * string, because there is nothing like MS_EXEC (we only have
++ * MS_NOEXEC in mount flags and we don't care about the original
++ * mount string in libmount for VFS options).
++ *
++ * This use-case makes sense for MS_SECURE flags only (see
+++ * mnt_optstr_get_flags() and mnt_context_merge_mflags()).
++ */
++ if (!(cxt->mountflags & MS_NOEXEC))
++ mnt_optstr_append_option(optstr, "exec", NULL);
++ if (!(cxt->mountflags & MS_NOSUID))
++ mnt_optstr_append_option(optstr, "suid", NULL);
++ if (!(cxt->mountflags & MS_NODEV))
++ mnt_optstr_append_option(optstr, "dev", NULL);
++ }
++
++ if (cxt->flags & MNT_FL_SAVED_USER)
++ rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user);
++ if (rc)
++ goto err;
++
++ /* remove userspace options with MNT_NOHLPS flag */
++ maps[0] = mnt_get_builtin_optmap(MNT_USERSPACE_MAP);
++ maps[1] = mnt_get_builtin_optmap(MNT_LINUX_MAP);
++ next = *optstr;
++
++ while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
++ const struct libmnt_optmap *ent;
++
++ mnt_optmap_get_entry(maps, 2, name, namesz, &ent);
++ if (ent && ent->id && (ent->mask & MNT_NOHLPS)) {
++ next = name;
++ rc = mnt_optstr_remove_option_at(optstr, name,
++ val ? val + valsz : name + namesz);
++ if (rc)
++ goto err;
++ }
++ }
+
+- return rc;
++ return rc;
+ err:
+- free(*optstr);
+- *optstr = NULL;
+- return rc;
++ free(*optstr);
++ *optstr = NULL;
++ return rc;
+ }
+
+ /*
+@@ -466,95 +466,95 @@
+ */
+ static int evaluate_permissions(struct libmnt_context *cxt)
+ {
+- unsigned long u_flags = 0;
++ unsigned long u_flags = 0;
+
+- assert(cxt);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++ assert(cxt);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+
+- if (!cxt->fs)
+- return 0;
++ if (!cxt->fs)
++ return 0;
+
+- DBG(CXT, ul_debugobj(cxt, "mount: evaluating permissions"));
+-
+- mnt_context_get_user_mflags(cxt, &u_flags);
+-
+- if (!mnt_context_is_restricted(cxt)) {
+- /*
+- * superuser mount
+- */
+- cxt->user_mountflags &= ~MNT_MS_OWNER;
+- cxt->user_mountflags &= ~MNT_MS_GROUP;
+- } else {
+- /*
+- * user mount
+- */
+- if (!mnt_context_tab_applied(cxt))
+- {
+- DBG(CXT, ul_debugobj(cxt, "perms: fstab not applied, ignore user mount"));
+- return -EPERM;
+- }
+-
+- /*
+- * MS_OWNERSECURE and MS_SECURE mount options are already
+- * applied by mnt_optstr_get_flags() in mnt_context_merge_mflags()
+- * if "user" (but no user=<name> !) options is set.
+- *
+- * Let's ignore all user=<name> (if <name> is set) requests.
+- */
+- if (cxt->user_mountflags & MNT_MS_USER) {
+- size_t valsz = 0;
+-
+- if (!mnt_optstr_get_option(cxt->fs->user_optstr,
+- "user", NULL, &valsz) && valsz) {
+-
+- DBG(CXT, ul_debugobj(cxt, "perms: user=<name> detected, ignore"));
+- cxt->user_mountflags &= ~MNT_MS_USER;
+- }
+- }
+-
+- /*
+- * MS_OWNER: Allow owners to mount when fstab contains the
+- * owner option. Note that this should never be used in a high
+- * security environment, but may be useful to give people at
+- * the console the possibility of mounting a floppy. MS_GROUP:
+- * Allow members of device group to mount. (Martin Dickopp)
+- */
+- if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) {
+- struct stat sb;
+- struct libmnt_cache *cache = NULL;
+- char *xsrc = NULL;
+- const char *srcpath = mnt_fs_get_srcpath(cxt->fs);
+-
+- if (!srcpath) { /* Ah... source is TAG */
+- cache = mnt_context_get_cache(cxt);
+- xsrc = mnt_resolve_spec(
+- mnt_context_get_source(cxt),
+- cache);
+- srcpath = xsrc;
+- }
+- if (!srcpath) {
+- DBG(CXT, ul_debugobj(cxt, "perms: src undefined"));
+- return -EPERM;
+- }
+-
+- if (strncmp(srcpath, "/dev/", 5) == 0 &&
+- stat(srcpath, &sb) == 0 &&
+- (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) ||
+- ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid))))
+-
+- cxt->user_mountflags |= MNT_MS_USER;
+-
+- if (!cache)
+- free(xsrc);
+- }
+-
+- if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) {
+- DBG(CXT, ul_debugobj(cxt, "permissions evaluation ends with -EPERMS"));
+- return -EPERM;
+- }
+- }
++ DBG(CXT, ul_debugobj(cxt, "mount: evaluating permissions"));
++
++ mnt_context_get_user_mflags(cxt, &u_flags);
++
++ if (!mnt_context_is_restricted(cxt)) {
++ /*
++ * superuser mount
++ */
++ cxt->user_mountflags &= ~MNT_MS_OWNER;
++ cxt->user_mountflags &= ~MNT_MS_GROUP;
++ } else {
++ /*
++ * user mount
++ */
++ if (!mnt_context_tab_applied(cxt))
++ {
++ DBG(CXT, ul_debugobj(cxt, "perms: fstab not applied, ignore user mount"));
++ return -EPERM;
++ }
++
++ /*
++ * MS_OWNERSECURE and MS_SECURE mount options are already
++ * applied by mnt_optstr_get_flags() in mnt_context_merge_mflags()
++ * if "user" (but no user=<name> !) options is set.
++ *
++ * Let's ignore all user=<name> (if <name> is set) requests.
++ */
++ if (cxt->user_mountflags & MNT_MS_USER) {
++ size_t valsz = 0;
++
++ if (!mnt_optstr_get_option(cxt->fs->user_optstr,
++ "user", NULL, &valsz) && valsz) {
++
++ DBG(CXT, ul_debugobj(cxt, "perms: user=<name> detected, ignore"));
++ cxt->user_mountflags &= ~MNT_MS_USER;
++ }
++ }
++
++ /*
++ * MS_OWNER: Allow owners to mount when fstab contains the
++ * owner option. Note that this should never be used in a high
++ * security environment, but may be useful to give people at
++ * the console the possibility of mounting a floppy. MS_GROUP:
++ * Allow members of device group to mount. (Martin Dickopp)
++ */
++ if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) {
++ struct stat sb;
++ struct libmnt_cache *cache = NULL;
++ char *xsrc = NULL;
++ const char *srcpath = mnt_fs_get_srcpath(cxt->fs);
++
++ if (!srcpath) { /* Ah... source is TAG */
++ cache = mnt_context_get_cache(cxt);
++ xsrc = mnt_resolve_spec(
++ mnt_context_get_source(cxt),
++ cache);
++ srcpath = xsrc;
++ }
++ if (!srcpath) {
++ DBG(CXT, ul_debugobj(cxt, "perms: src undefined"));
++ return -EPERM;
++ }
++
++ if (strncmp(srcpath, "/dev/", 5) == 0 &&
++ stat(srcpath, &sb) == 0 &&
++ (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) ||
++ ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid))))
++
++ cxt->user_mountflags |= MNT_MS_USER;
++
++ if (!cache)
++ free(xsrc);
++ }
++
++ if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) {
++ DBG(CXT, ul_debugobj(cxt, "permissions evaluation ends with -EPERMS"));
++ return -EPERM;
++ }
++ }
+
+- return 0;
++ return 0;
+ }
+
+ /*
+@@ -568,191 +568,191 @@
+ */
+ int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg)
+ {
+- int rc = -EINVAL;
++ int rc = -EINVAL;
+
+- assert(cxt);
+- assert(cxt->action == MNT_ACT_MOUNT);
++ assert(cxt);
++ assert(cxt->action == MNT_ACT_MOUNT);
+
+- switch(c) {
+- case 'f':
+- rc = mnt_context_enable_fake(cxt, TRUE);
+- break;
+- case 'n':
+- rc = mnt_context_disable_mtab(cxt, TRUE);
+- break;
+- case 'r':
+- rc = mnt_context_append_options(cxt, "ro");
+- break;
+- case 'v':
+- rc = mnt_context_enable_verbose(cxt, TRUE);
+- break;
+- case 'w':
+- rc = mnt_context_append_options(cxt, "rw");
+- break;
+- case 'o':
+- if (arg)
+- rc = mnt_context_append_options(cxt, arg);
+- break;
+- case 's':
+- rc = mnt_context_enable_sloppy(cxt, TRUE);
+- break;
+- case 't':
+- if (arg)
+- rc = mnt_context_set_fstype(cxt, arg);
+- break;
+- case 'N':
+- if (arg)
+- rc = mnt_context_set_target_ns(cxt, arg);
+- break;
+- default:
+- return 1;
+- }
++ switch(c) {
++ case 'f':
++ rc = mnt_context_enable_fake(cxt, TRUE);
++ break;
++ case 'n':
++ rc = mnt_context_disable_mtab(cxt, TRUE);
++ break;
++ case 'r':
++ rc = mnt_context_append_options(cxt, "ro");
++ break;
++ case 'v':
++ rc = mnt_context_enable_verbose(cxt, TRUE);
++ break;
++ case 'w':
++ rc = mnt_context_append_options(cxt, "rw");
++ break;
++ case 'o':
++ if (arg)
++ rc = mnt_context_append_options(cxt, arg);
++ break;
++ case 's':
++ rc = mnt_context_enable_sloppy(cxt, TRUE);
++ break;
++ case 't':
++ if (arg)
++ rc = mnt_context_set_fstype(cxt, arg);
++ break;
++ case 'N':
++ if (arg)
++ rc = mnt_context_set_target_ns(cxt, arg);
++ break;
++ default:
++ return 1;
++ }
+
+- return rc;
++ return rc;
+ }
+
+ static int exec_helper(struct libmnt_context *cxt)
+ {
+- char *o = NULL, *namespace = NULL;
+- struct libmnt_ns *ns_tgt = mnt_context_get_target_ns(cxt);
+- int rc;
+- pid_t pid;
+-
+- assert(cxt);
+- assert(cxt->fs);
+- assert(cxt->helper);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+-
+- DBG(CXT, ul_debugobj(cxt, "mount: executing helper %s", cxt->helper));
+-
+- rc = generate_helper_optstr(cxt, &o);
+- if (rc)
+- return -EINVAL;
+-
+- if (ns_tgt->fd != -1
+- && asprintf(&namespace, "/proc/%i/fd/%i",
+- getpid(), ns_tgt->fd) == -1) {
+- free(o);
+- return -ENOMEM;
+- }
+-
+- DBG_FLUSH;
+-
+- pid = fork();
+- switch (pid) {
+- case 0:
+- {
+- const char *args[14], *type;
+- int i = 0;
+-
+- if (setgid(getgid()) < 0)
+- _exit(EXIT_FAILURE);
+-
+- if (setuid(getuid()) < 0)
+- _exit(EXIT_FAILURE);
+-
+- if (!mnt_context_switch_origin_ns(cxt))
+- _exit(EXIT_FAILURE);
+-
+- type = mnt_fs_get_fstype(cxt->fs);
+-
+- args[i++] = cxt->helper; /* 1 */
+- args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */
+- args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */
+-
+- if (mnt_context_is_sloppy(cxt))
+- args[i++] = "-s"; /* 4 */
+- if (mnt_context_is_fake(cxt))
+- args[i++] = "-f"; /* 5 */
+- if (mnt_context_is_nomtab(cxt))
+- args[i++] = "-n"; /* 6 */
+- if (mnt_context_is_verbose(cxt))
+- args[i++] = "-v"; /* 7 */
+- if (o) {
+- args[i++] = "-o"; /* 8 */
+- args[i++] = o; /* 9 */
+- }
+- if (type
+- && strchr(type, '.')
+- && !endswith(cxt->helper, type)) {
+- args[i++] = "-t"; /* 10 */
+- args[i++] = type; /* 11 */
+- }
+- if (namespace) {
+- args[i++] = "-N"; /* 11 */
+- args[i++] = namespace; /* 12 */
+- }
+- args[i] = NULL; /* 13 */
+- for (i = 0; args[i]; i++)
+- DBG(CXT, ul_debugobj(cxt, "argv[%d] = \"%s\"",
+- i, args[i]));
+- DBG_FLUSH;
+- execv(cxt->helper, (char * const *) args);
+- _exit(EXIT_FAILURE);
+- }
+- default:
+- {
+- int st;
+-
+- if (waitpid(pid, &st, 0) == (pid_t) -1) {
+- cxt->helper_status = -1;
+- rc = -errno;
+- } else {
+- cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;
+- cxt->helper_exec_status = rc = 0;
+- }
+- DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]",
+- cxt->helper,
+- cxt->helper_status, rc,
+- rc ? " waitpid failed" : ""));
+- break;
+- }
+-
+- case -1:
+- cxt->helper_exec_status = rc = -errno;
+- DBG(CXT, ul_debugobj(cxt, "fork() failed"));
+- break;
+- }
++ char *o = NULL, *namespace = NULL;
++ struct libmnt_ns *ns_tgt = mnt_context_get_target_ns(cxt);
++ int rc;
++ pid_t pid;
++
++ assert(cxt);
++ assert(cxt->fs);
++ assert(cxt->helper);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++
++ DBG(CXT, ul_debugobj(cxt, "mount: executing helper %s", cxt->helper));
++
++ rc = generate_helper_optstr(cxt, &o);
++ if (rc)
++ return -EINVAL;
++
++ if (ns_tgt->fd != -1
++ && asprintf(&namespace, "/proc/%i/fd/%i",
++ getpid(), ns_tgt->fd) == -1) {
++ free(o);
++ return -ENOMEM;
++ }
++
++ DBG_FLUSH;
++
++ pid = fork();
++ switch (pid) {
++ case 0:
++ {
++ const char *args[14], *type;
++ int i = 0;
++
++ if (setgid(getgid()) < 0)
++ _exit(EXIT_FAILURE);
++
++ if (setuid(getuid()) < 0)
++ _exit(EXIT_FAILURE);
++
++ if (!mnt_context_switch_origin_ns(cxt))
++ _exit(EXIT_FAILURE);
++
++ type = mnt_fs_get_fstype(cxt->fs);
++
++ args[i++] = cxt->helper; /* 1 */
++ args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */
++ args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */
++
++ if (mnt_context_is_sloppy(cxt))
++ args[i++] = "-s"; /* 4 */
++ if (mnt_context_is_fake(cxt))
++ args[i++] = "-f"; /* 5 */
++ if (mnt_context_is_nomtab(cxt))
++ args[i++] = "-n"; /* 6 */
++ if (mnt_context_is_verbose(cxt))
++ args[i++] = "-v"; /* 7 */
++ if (o) {
++ args[i++] = "-o"; /* 8 */
++ args[i++] = o; /* 9 */
++ }
++ if (type
++ && strchr(type, '.')
++ && !endswith(cxt->helper, type)) {
++ args[i++] = "-t"; /* 10 */
++ args[i++] = type; /* 11 */
++ }
++ if (namespace) {
++ args[i++] = "-N"; /* 11 */
++ args[i++] = namespace; /* 12 */
++ }
++ args[i] = NULL; /* 13 */
++ for (i = 0; args[i]; i++)
++ DBG(CXT, ul_debugobj(cxt, "argv[%d] = \"%s\"",
++ i, args[i]));
++ DBG_FLUSH;
++ execv(cxt->helper, (char * const *) args);
++ _exit(EXIT_FAILURE);
++ }
++ default:
++ {
++ int st;
++
++ if (waitpid(pid, &st, 0) == (pid_t) -1) {
++ cxt->helper_status = -1;
++ rc = -errno;
++ } else {
++ cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;
++ cxt->helper_exec_status = rc = 0;
++ }
++ DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]",
++ cxt->helper,
++ cxt->helper_status, rc,
++ rc ? " waitpid failed" : ""));
++ break;
++ }
++
++ case -1:
++ cxt->helper_exec_status = rc = -errno;
++ DBG(CXT, ul_debugobj(cxt, "fork() failed"));
++ break;
++ }
+
+- free(o);
+- return rc;
++ free(o);
++ return rc;
+ }
+
+ static int do_mount_additional(struct libmnt_context *cxt,
+- const char *target,
+- unsigned long flags,
+- int *syserr)
+-{
+- struct list_head *p;
+-
+- assert(cxt);
+- assert(target);
+-
+- if (syserr)
+- *syserr = 0;
+-
+- list_for_each(p, &cxt->addmounts) {
+- int rc;
+- struct libmnt_addmount *ad =
+- list_entry(p, struct libmnt_addmount, mounts);
+-
+- DBG(CXT, ul_debugobj(cxt, "mount(2) changing flag: 0x%08lx %s",
+- ad->mountflags,
+- ad->mountflags & MS_REC ? " (recursive)" : ""));
+-
+- rc = mount("none", target, NULL,
+- ad->mountflags | (flags & MS_SILENT), NULL);
+- if (rc) {
+- if (syserr)
+- *syserr = -errno;
+- DBG(CXT, ul_debugobj(cxt,
+- "mount(2) failed [errno=%d %m]",
+- errno));
+- return rc;
+- }
+- }
++ const char *target,
++ unsigned long flags,
++ int *syserr)
++{
++ struct list_head *p;
++
++ assert(cxt);
++ assert(target);
++
++ if (syserr)
++ *syserr = 0;
++
++ list_for_each(p, &cxt->addmounts) {
++ int rc;
++ struct libmnt_addmount *ad =
++ list_entry(p, struct libmnt_addmount, mounts);
++
++ DBG(CXT, ul_debugobj(cxt, "mount(2) changing flag: 0x%08lx %s",
++ ad->mountflags,
++ ad->mountflags & MS_REC ? " (recursive)" : ""));
++
++ rc = mount("none", target, NULL,
++ ad->mountflags | (flags & MS_SILENT), NULL);
++ if (rc) {
++ if (syserr)
++ *syserr = -errno;
++ DBG(CXT, ul_debugobj(cxt,
++ "mount(2) failed [errno=%d %m]",
++ errno));
++ return rc;
++ }
++ }
+
+- return 0;
++ return 0;
+ }
+
+ /*
+@@ -765,193 +765,193 @@
+ */
+ static int do_mount(struct libmnt_context *cxt, const char *try_type)
+ {
+- int rc = 0;
+- const char *src, *target, *type;
+- unsigned long flags;
+-
+- assert(cxt);
+- assert(cxt->fs);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+-
+- if (try_type && !cxt->helper) {
+- rc = mnt_context_prepare_helper(cxt, "mount", try_type);
+- if (rc)
+- return rc;
+- }
+-
+- flags = cxt->mountflags;
+- src = mnt_fs_get_srcpath(cxt->fs);
+- target = mnt_fs_get_target(cxt->fs);
+-
+- if (cxt->helper) {
+- rc = exec_helper(cxt);
+-
+- if (mnt_context_helper_executed(cxt)
+- && mnt_context_get_helper_status(cxt) == 0
+- && !list_empty(&cxt->addmounts)
+- && do_mount_additional(cxt, target, flags, NULL))
+-
+- return -MNT_ERR_APPLYFLAGS;
+- return rc;
+- }
+-
+- if (!target)
+- return -EINVAL;
+- if (!src) {
+- /* unnecessary, should be already resolved in
+- * mnt_context_prepare_srcpath(), but to be sure... */
+- DBG(CXT, ul_debugobj(cxt, "WARNING: source is NULL -- using \"none\"!"));
+- src = "none";
+- }
+- type = try_type ? : mnt_fs_get_fstype(cxt->fs);
+-
+- if (try_type)
+- flags |= MS_SILENT;
+-
+- DBG(CXT, ul_debugobj(cxt, "%smount(2) "
+- "[source=%s, target=%s, type=%s, "
+- " mountflags=0x%08lx, mountdata=%s]",
+- mnt_context_is_fake(cxt) ? "(FAKE) " : "",
+- src, target, type,
+- flags, cxt->mountdata ? "yes" : "<none>"));
+-
+- if (mnt_context_is_fake(cxt)) {
+- /*
+- * fake
+- */
+- cxt->syscall_status = 0;
+-
+- } else if (mnt_context_propagation_only(cxt)) {
+- /*
+- * propagation flags *only*
+- */
+- if (do_mount_additional(cxt, target, flags, &cxt->syscall_status))
+- return -MNT_ERR_APPLYFLAGS;
+- } else {
+- /*
+- * regular mount
+- */
+- if (mount(src, target, type, flags, cxt->mountdata)) {
+- cxt->syscall_status = -errno;
+- DBG(CXT, ul_debugobj(cxt, "mount(2) failed [errno=%d %m]",
+- -cxt->syscall_status));
+- return -cxt->syscall_status;
+- }
+- DBG(CXT, ul_debugobj(cxt, " success"));
+- cxt->syscall_status = 0;
+-
+- /*
+- * additional mounts for extra propagation flags
+- */
+- if (!list_empty(&cxt->addmounts)
+- && do_mount_additional(cxt, target, flags, NULL)) {
+-
+- /* TODO: call umount? */
+- return -MNT_ERR_APPLYFLAGS;
+- }
+- }
+-
+- if (try_type && cxt->update) {
+- struct libmnt_fs *fs = mnt_update_get_fs(cxt->update);
+- if (fs)
+- rc = mnt_fs_set_fstype(fs, try_type);
+- }
++ int rc = 0;
++ const char *src, *target, *type;
++ unsigned long flags;
++
++ assert(cxt);
++ assert(cxt->fs);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++
++ if (try_type && !cxt->helper) {
++ rc = mnt_context_prepare_helper(cxt, "mount", try_type);
++ if (rc)
++ return rc;
++ }
++
++ flags = cxt->mountflags;
++ src = mnt_fs_get_srcpath(cxt->fs);
++ target = mnt_fs_get_target(cxt->fs);
++
++ if (cxt->helper) {
++ rc = exec_helper(cxt);
++
++ if (mnt_context_helper_executed(cxt)
++ && mnt_context_get_helper_status(cxt) == 0
++ && !list_empty(&cxt->addmounts)
++ && do_mount_additional(cxt, target, flags, NULL))
++
++ return -MNT_ERR_APPLYFLAGS;
++ return rc;
++ }
++
++ if (!target)
++ return -EINVAL;
++ if (!src) {
++ /* unnecessary, should be already resolved in
++ * mnt_context_prepare_srcpath(), but to be sure... */
++ DBG(CXT, ul_debugobj(cxt, "WARNING: source is NULL -- using \"none\"!"));
++ src = "none";
++ }
++ type = try_type ? : mnt_fs_get_fstype(cxt->fs);
++
++ if (try_type)
++ flags |= MS_SILENT;
++
++ DBG(CXT, ul_debugobj(cxt, "%smount(2) "
++ "[source=%s, target=%s, type=%s, "
++ " mountflags=0x%08lx, mountdata=%s]",
++ mnt_context_is_fake(cxt) ? "(FAKE) " : "",
++ src, target, type,
++ flags, cxt->mountdata ? "yes" : "<none>"));
++
++ if (mnt_context_is_fake(cxt)) {
++ /*
++ * fake
++ */
++ cxt->syscall_status = 0;
++
++ } else if (mnt_context_propagation_only(cxt)) {
++ /*
++ * propagation flags *only*
++ */
++ if (do_mount_additional(cxt, target, flags, &cxt->syscall_status))
++ return -MNT_ERR_APPLYFLAGS;
++ } else {
++ /*
++ * regular mount
++ */
++ if (mount(src, target, type, flags, cxt->mountdata)) {
++ cxt->syscall_status = -errno;
++ DBG(CXT, ul_debugobj(cxt, "mount(2) failed [errno=%d %m]",
++ -cxt->syscall_status));
++ return -cxt->syscall_status;
++ }
++ DBG(CXT, ul_debugobj(cxt, " success"));
++ cxt->syscall_status = 0;
++
++ /*
++ * additional mounts for extra propagation flags
++ */
++ if (!list_empty(&cxt->addmounts)
++ && do_mount_additional(cxt, target, flags, NULL)) {
++
++ /* TODO: call umount? */
++ return -MNT_ERR_APPLYFLAGS;
++ }
++ }
++
++ if (try_type && cxt->update) {
++ struct libmnt_fs *fs = mnt_update_get_fs(cxt->update);
++ if (fs)
++ rc = mnt_fs_set_fstype(fs, try_type);
++ }
+
+- return rc;
++ return rc;
+ }
+
+ /* try mount(2) for all items in comma separated list of the filesystem @types */
+ static int do_mount_by_types(struct libmnt_context *cxt, const char *types)
+ {
+- int rc = -EINVAL;
+- char *p, *p0;
++ int rc = -EINVAL;
++ char *p, *p0;
+
+- assert(cxt);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++ assert(cxt);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+
+- DBG(CXT, ul_debugobj(cxt, "trying to mount by FS list '%s'", types));
++ DBG(CXT, ul_debugobj(cxt, "trying to mount by FS list '%s'", types));
+
+- p0 = p = strdup(types);
+- if (!p)
+- return -ENOMEM;
+- do {
+- char *autotype = NULL;
+- char *end = strchr(p, ',');
+-
+- if (end)
+- *end = '\0';
+-
+- DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p));
+-
+- /* Let's support things like "udf,iso9660,auto" */
+- if (strcmp(p, "auto") == 0) {
+- rc = mnt_context_guess_srcpath_fstype(cxt, &autotype);
+- if (rc) {
+- DBG(CXT, ul_debugobj(cxt, "failed to guess FS type [rc=%d]", rc));
+- free(p0);
+- free(autotype);
+- return rc;
+- }
+- p = autotype;
+- DBG(CXT, ul_debugobj(cxt, " --> '%s'", p));
+- }
+-
+- if (p)
+- rc = do_mount(cxt, p);
+- p = end ? end + 1 : NULL;
+- free(autotype);
+- } while (!mnt_context_get_status(cxt) && p);
++ p0 = p = strdup(types);
++ if (!p)
++ return -ENOMEM;
++ do {
++ char *autotype = NULL;
++ char *end = strchr(p, ',');
++
++ if (end)
++ *end = '\0';
++
++ DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p));
++
++ /* Let's support things like "udf,iso9660,auto" */
++ if (strcmp(p, "auto") == 0) {
++ rc = mnt_context_guess_srcpath_fstype(cxt, &autotype);
++ if (rc) {
++ DBG(CXT, ul_debugobj(cxt, "failed to guess FS type [rc=%d]", rc));
++ free(p0);
++ free(autotype);
++ return rc;
++ }
++ p = autotype;
++ DBG(CXT, ul_debugobj(cxt, " --> '%s'", p));
++ }
++
++ if (p)
++ rc = do_mount(cxt, p);
++ p = end ? end + 1 : NULL;
++ free(autotype);
++ } while (!mnt_context_get_status(cxt) && p);
+
+- free(p0);
+- return rc;
++ free(p0);
++ return rc;
+ }
+
+
+ static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern)
+ {
+- int neg = pattern && strncmp(pattern, "no", 2) == 0;
+- int rc = -EINVAL;
+- char **filesystems, **fp;
+- struct libmnt_ns *ns_old;
+-
+- assert(cxt);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+-
+- /*
+- * Use the pattern as list of the filesystems
+- */
+- if (!neg && pattern) {
+- DBG(CXT, ul_debugobj(cxt, "use FS pattern as FS list"));
+- return do_mount_by_types(cxt, pattern);
+- }
+-
+- DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern '%s'", pattern));
+-
+- /*
+- * Apply pattern to /etc/filesystems and /proc/filesystems
+- */
+- ns_old = mnt_context_switch_origin_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
+- rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL);
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
+- if (rc)
+- return rc;
+-
+- if (filesystems == NULL)
+- return -MNT_ERR_NOFSTYPE;
+-
+- for (fp = filesystems; *fp; fp++) {
+- rc = do_mount(cxt, *fp);
+- if (mnt_context_get_status(cxt))
+- break;
+- if (mnt_context_get_syscall_errno(cxt) != EINVAL &&
+- mnt_context_get_syscall_errno(cxt) != ENODEV)
+- break;
+- }
+- mnt_free_filesystems(filesystems);
+- return rc;
++ int neg = pattern && strncmp(pattern, "no", 2) == 0;
++ int rc = -EINVAL;
++ char **filesystems, **fp;
++ struct libmnt_ns *ns_old;
++
++ assert(cxt);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++
++ /*
++ * Use the pattern as list of the filesystems
++ */
++ if (!neg && pattern) {
++ DBG(CXT, ul_debugobj(cxt, "use FS pattern as FS list"));
++ return do_mount_by_types(cxt, pattern);
++ }
++
++ DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern '%s'", pattern));
++
++ /*
++ * Apply pattern to /etc/filesystems and /proc/filesystems
++ */
++ ns_old = mnt_context_switch_origin_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
++ rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL);
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
++ if (rc)
++ return rc;
++
++ if (filesystems == NULL)
++ return -MNT_ERR_NOFSTYPE;
++
++ for (fp = filesystems; *fp; fp++) {
++ rc = do_mount(cxt, *fp);
++ if (mnt_context_get_status(cxt))
++ break;
++ if (mnt_context_get_syscall_errno(cxt) != EINVAL &&
++ mnt_context_get_syscall_errno(cxt) != ENODEV)
++ break;
++ }
++ mnt_free_filesystems(filesystems);
++ return rc;
+ }
+
+ /**
+@@ -964,53 +964,53 @@
+ */
+ int mnt_context_prepare_mount(struct libmnt_context *cxt)
+ {
+- int rc = -EINVAL;
+- struct libmnt_ns *ns_old;
++ int rc = -EINVAL;
++ struct libmnt_ns *ns_old;
+
+- if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs))
+- return -EINVAL;
+- if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs))
+- return -EINVAL;
+- if (cxt->flags & MNT_FL_PREPARED)
+- return 0;
+-
+- assert(cxt->helper_exec_status == 1);
+- assert(cxt->syscall_status == 1);
+-
+- cxt->action = MNT_ACT_MOUNT;
+-
+- ns_old = mnt_context_switch_target_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
+-
+- DBG(CXT, ul_debugobj(cxt, "mount: preparing"));
+-
+- rc = mnt_context_apply_fstab(cxt);
+- if (!rc)
+- rc = mnt_context_merge_mflags(cxt);
+- if (!rc)
+- rc = evaluate_permissions(cxt);
+- if (!rc)
+- rc = fix_optstr(cxt);
+- if (!rc)
+- rc = mnt_context_prepare_srcpath(cxt);
+- if (!rc)
+- rc = mnt_context_guess_fstype(cxt);
+- if (!rc)
+- rc = mnt_context_prepare_target(cxt);
+- if (!rc)
+- rc = mnt_context_prepare_helper(cxt, "mount", NULL);
+- if (rc) {
+- DBG(CXT, ul_debugobj(cxt, "mount: preparing failed"));
+- goto end;
+- }
+- cxt->flags |= MNT_FL_PREPARED;
++ if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs))
++ return -EINVAL;
++ if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs))
++ return -EINVAL;
++ if (cxt->flags & MNT_FL_PREPARED)
++ return 0;
++
++ assert(cxt->helper_exec_status == 1);
++ assert(cxt->syscall_status == 1);
++
++ cxt->action = MNT_ACT_MOUNT;
++
++ ns_old = mnt_context_switch_target_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
++
++ DBG(CXT, ul_debugobj(cxt, "mount: preparing"));
++
++ rc = mnt_context_apply_fstab(cxt);
++ if (!rc)
++ rc = mnt_context_merge_mflags(cxt);
++ if (!rc)
++ rc = evaluate_permissions(cxt);
++ if (!rc)
++ rc = fix_optstr(cxt);
++ if (!rc)
++ rc = mnt_context_prepare_srcpath(cxt);
++ if (!rc)
++ rc = mnt_context_guess_fstype(cxt);
++ if (!rc)
++ rc = mnt_context_prepare_target(cxt);
++ if (!rc)
++ rc = mnt_context_prepare_helper(cxt, "mount", NULL);
++ if (rc) {
++ DBG(CXT, ul_debugobj(cxt, "mount: preparing failed"));
++ goto end;
++ }
++ cxt->flags |= MNT_FL_PREPARED;
+
+ end:
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
+
+- return rc;
++ return rc;
+ }
+
+ /**
+@@ -1038,87 +1038,87 @@
+ */
+ int mnt_context_do_mount(struct libmnt_context *cxt)
+ {
+- const char *type;
+- int res;
+- struct libmnt_ns *ns_old;
+-
+- assert(cxt);
+- assert(cxt->fs);
+- assert(cxt->helper_exec_status == 1);
+- assert(cxt->syscall_status == 1);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+- assert((cxt->flags & MNT_FL_PREPARED));
+- assert((cxt->action == MNT_ACT_MOUNT));
+-
+- DBG(CXT, ul_debugobj(cxt, "mount: do mount"));
+-
+- if (!(cxt->flags & MNT_FL_MOUNTDATA))
+- cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs);
+-
+- ns_old = mnt_context_switch_target_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
+-
+- type = mnt_fs_get_fstype(cxt->fs);
+- if (type) {
+- if (strchr(type, ','))
+- /* this only happens if fstab contains a list of filesystems */
+- res = do_mount_by_types(cxt, type);
+- else
+- res = do_mount(cxt, NULL);
+- } else
+- res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
++ const char *type;
++ int res;
++ struct libmnt_ns *ns_old;
++
++ assert(cxt);
++ assert(cxt->fs);
++ assert(cxt->helper_exec_status == 1);
++ assert(cxt->syscall_status == 1);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++ assert((cxt->flags & MNT_FL_PREPARED));
++ assert((cxt->action == MNT_ACT_MOUNT));
++
++ DBG(CXT, ul_debugobj(cxt, "mount: do mount"));
++
++ if (!(cxt->flags & MNT_FL_MOUNTDATA))
++ cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs);
++
++ ns_old = mnt_context_switch_target_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
++
++ type = mnt_fs_get_fstype(cxt->fs);
++ if (type) {
++ if (strchr(type, ','))
++ /* this only happens if fstab contains a list of filesystems */
++ res = do_mount_by_types(cxt, type);
++ else
++ res = do_mount(cxt, NULL);
++ } else
++ res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
+
+ #ifdef USE_LIBMOUNT_SUPPORT_MTAB
+- if (mnt_context_get_status(cxt)
+- && !mnt_context_is_fake(cxt)
+- && !cxt->helper
+- && mnt_context_mtab_writable(cxt)) {
+-
+- int is_rdonly = -1;
+-
+- DBG(CXT, ul_debugobj(cxt, "checking for RDONLY mismatch"));
+-
+- /*
+- * Mounted by mount(2), do some post-mount checks
+- *
+- * Kernel can be used to use MS_RDONLY for bind mounts, but the
+- * read-only request could be silently ignored. Check it to
+- * avoid 'ro' in mtab and 'rw' in /proc/mounts.
+- */
+- if ((cxt->mountflags & MS_BIND)
+- && (cxt->mountflags & MS_RDONLY)) {
+-
+- if (is_rdonly < 0)
+- is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt));
+- if (!is_rdonly)
+- mnt_context_set_mflags(cxt, cxt->mountflags & ~MS_RDONLY);
+- }
+-
+-
+- /* Kernel can silently add MS_RDONLY flag when mounting file
+- * system that does not have write support. Check this to avoid
+- * 'ro' in /proc/mounts and 'rw' in mtab.
+- */
+- if (!(cxt->mountflags & (MS_RDONLY | MS_MOVE))
+- && !mnt_context_propagation_only(cxt)) {
+-
+- if (is_rdonly < 0)
+- is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt));
+- if (is_rdonly)
+- mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);
+- }
+- }
++ if (mnt_context_get_status(cxt)
++ && !mnt_context_is_fake(cxt)
++ && !cxt->helper
++ && mnt_context_mtab_writable(cxt)) {
++
++ int is_rdonly = -1;
++
++ DBG(CXT, ul_debugobj(cxt, "checking for RDONLY mismatch"));
++
++ /*
++ * Mounted by mount(2), do some post-mount checks
++ *
++ * Kernel can be used to use MS_RDONLY for bind mounts, but the
++ * read-only request could be silently ignored. Check it to
++ * avoid 'ro' in mtab and 'rw' in /proc/mounts.
++ */
++ if ((cxt->mountflags & MS_BIND)
++ && (cxt->mountflags & MS_RDONLY)) {
++
++ if (is_rdonly < 0)
++ is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt));
++ if (!is_rdonly)
++ mnt_context_set_mflags(cxt, cxt->mountflags & ~MS_RDONLY);
++ }
++
++
++ /* Kernel can silently add MS_RDONLY flag when mounting file
++ * system that does not have write support. Check this to avoid
++ * 'ro' in /proc/mounts and 'rw' in mtab.
++ */
++ if (!(cxt->mountflags & (MS_RDONLY | MS_MOVE))
++ && !mnt_context_propagation_only(cxt)) {
++
++ if (is_rdonly < 0)
++ is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt));
++ if (is_rdonly)
++ mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);
++ }
++ }
+ #endif
+
+- /* Cleanup will be immediate on failure, and deferred to umount on success */
+- if (mnt_context_is_veritydev(cxt))
+- mnt_context_deferred_delete_veritydev(cxt);
++ /* Cleanup will be immediate on failure, and deferred to umount on success */
++ if (mnt_context_is_veritydev(cxt))
++ mnt_context_deferred_delete_veritydev(cxt);
+
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
+
+- return res;
++ return res;
+ }
+
+ /*
+@@ -1128,27 +1128,27 @@
+ */
+ static struct libmnt_fs *get_already_mounted_source(struct libmnt_context *cxt)
+ {
+- const char *src;
+- struct libmnt_table *tb;
++ const char *src;
++ struct libmnt_table *tb;
+
+- assert(cxt);
++ assert(cxt);
+
+- src = mnt_fs_get_srcpath(cxt->fs);
++ src = mnt_fs_get_srcpath(cxt->fs);
+
+- if (src && mnt_context_get_mtab(cxt, &tb) == 0) {
+- struct libmnt_iter itr;
+- struct libmnt_fs *fs;
+-
+- mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+- while (mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- const char *s = mnt_fs_get_srcpath(fs),
+- *t = mnt_fs_get_target(fs);
+-
+- if (t && s && mnt_fs_streq_srcpath(fs, src))
+- return fs;
+- }
+- }
+- return NULL;
++ if (src && mnt_context_get_mtab(cxt, &tb) == 0) {
++ struct libmnt_iter itr;
++ struct libmnt_fs *fs;
++
++ mnt_reset_iter(&itr, MNT_ITER_FORWARD);
++ while (mnt_table_next_fs(tb, &itr, &fs) == 0) {
++ const char *s = mnt_fs_get_srcpath(fs),
++ *t = mnt_fs_get_target(fs);
++
++ if (t && s && mnt_fs_streq_srcpath(fs, src))
++ return fs;
++ }
++ }
++ return NULL;
+ }
+
+ /*
+@@ -1157,10 +1157,10 @@
+ */
+ static int is_source_already_rdonly(struct libmnt_context *cxt)
+ {
+- struct libmnt_fs *fs = get_already_mounted_source(cxt);
+- const char *opts = fs ? mnt_fs_get_fs_options(fs) : NULL;
++ struct libmnt_fs *fs = get_already_mounted_source(cxt);
++ const char *opts = fs ? mnt_fs_get_fs_options(fs) : NULL;
+
+- return opts && mnt_optstr_get_option(opts, "ro", NULL, NULL) == 0;
++ return opts && mnt_optstr_get_option(opts, "ro", NULL, NULL) == 0;
+ }
+
+ /**
+@@ -1174,17 +1174,17 @@
+ */
+ int mnt_context_finalize_mount(struct libmnt_context *cxt)
+ {
+- int rc;
++ int rc;
+
+- assert(cxt);
+- assert(cxt->fs);
+- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
+- assert((cxt->flags & MNT_FL_PREPARED));
+-
+- rc = mnt_context_prepare_update(cxt);
+- if (!rc)
+- rc = mnt_context_update_tabs(cxt);
+- return rc;
++ assert(cxt);
++ assert(cxt->fs);
++ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
++ assert((cxt->flags & MNT_FL_PREPARED));
++
++ rc = mnt_context_prepare_update(cxt);
++ if (!rc)
++ rc = mnt_context_update_tabs(cxt);
++ return rc;
+ }
+
+ /**
+@@ -1195,9 +1195,9 @@
+ *
+ * This is similar to:
+ *
+- * mnt_context_prepare_mount(cxt);
+- * mnt_context_do_mount(cxt);
+- * mnt_context_finalize_mount(cxt);
++ * mnt_context_prepare_mount(cxt);
++ * mnt_context_do_mount(cxt);
++ * mnt_context_finalize_mount(cxt);
+ *
+ * See also mnt_context_disable_helpers().
+ *
+@@ -1232,7 +1232,7 @@
+ * rc = mnt_context_get_excode(cxt, rc, buf, sizeof(buf));
+ * if (buf)
+ * warnx(_("%s: %s"), mnt_context_get_target(cxt), buf);
+- * return rc; // MNT_EX_*
++ * return rc; // MNT_EX_*
+ * </programlisting>
+ * </informalexample>
+ *
+@@ -1242,58 +1242,58 @@
+ */
+ int mnt_context_mount(struct libmnt_context *cxt)
+ {
+- int rc;
+- struct libmnt_ns *ns_old;
++ int rc;
++ struct libmnt_ns *ns_old;
+
+- assert(cxt);
+- assert(cxt->fs);
+- assert(cxt->helper_exec_status == 1);
+- assert(cxt->syscall_status == 1);
+-
+- ns_old = mnt_context_switch_target_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
++ assert(cxt);
++ assert(cxt->fs);
++ assert(cxt->helper_exec_status == 1);
++ assert(cxt->syscall_status == 1);
++
++ ns_old = mnt_context_switch_target_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
+
+ again:
+- rc = mnt_context_prepare_mount(cxt);
+- if (!rc)
+- rc = mnt_context_prepare_update(cxt);
+- if (!rc)
+- rc = mnt_context_do_mount(cxt);
+- if (!rc)
+- rc = mnt_context_update_tabs(cxt);
+-
+- /*
+- * Read-only device or already read-only mounted FS.
+- * Try mount the filesystem read-only.
+- */
+- if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */
+- || mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */
+- || mnt_context_get_syscall_errno(cxt) == EACCES /* syscall failed with EACCES */
+- || (mnt_context_get_syscall_errno(cxt) == EBUSY /* already ro-mounted FS */
+- && is_source_already_rdonly(cxt)))
+- {
+- unsigned long mflags = 0;
+-
+- mnt_context_get_mflags(cxt, &mflags);
+-
+- if (!(mflags & MS_RDONLY) /* not yet RDONLY */
+- && !(mflags & MS_REMOUNT) /* not remount */
+- && !(mflags & MS_BIND) /* not bin mount */
+- && !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */
+-
+- assert(!(cxt->flags & MNT_FL_FORCED_RDONLY));
+- DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY."));
+-
+- mnt_context_reset_status(cxt);
+- mnt_context_set_mflags(cxt, mflags | MS_RDONLY);
+- cxt->flags |= MNT_FL_FORCED_RDONLY;
+- goto again;
+- }
+- }
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
+- return rc;
++ rc = mnt_context_prepare_mount(cxt);
++ if (!rc)
++ rc = mnt_context_prepare_update(cxt);
++ if (!rc)
++ rc = mnt_context_do_mount(cxt);
++ if (!rc)
++ rc = mnt_context_update_tabs(cxt);
++
++ /*
++ * Read-only device or already read-only mounted FS.
++ * Try mount the filesystem read-only.
++ */
++ if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */
++ || mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */
++ || mnt_context_get_syscall_errno(cxt) == EACCES /* syscall failed with EACCES */
++ || (mnt_context_get_syscall_errno(cxt) == EBUSY /* already ro-mounted FS */
++ && is_source_already_rdonly(cxt)))
++ {
++ unsigned long mflags = 0;
++
++ mnt_context_get_mflags(cxt, &mflags);
++
++ if (!(mflags & MS_RDONLY) /* not yet RDONLY */
++ && !(mflags & MS_REMOUNT) /* not remount */
++ && !(mflags & MS_BIND) /* not bin mount */
++ && !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */
++
++ assert(!(cxt->flags & MNT_FL_FORCED_RDONLY));
++ DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY."));
++
++ mnt_context_reset_status(cxt);
++ mnt_context_set_mflags(cxt, mflags | MS_RDONLY);
++ cxt->flags |= MNT_FL_FORCED_RDONLY;
++ goto again;
++ }
++ }
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
++ return rc;
+ }
+
+ /**
+@@ -1308,8 +1308,8 @@
+ * mnt_context_get_fstab()). See also mnt_context_set_fstab().
+ *
+ * You can filter out filesystems by:
+- * mnt_context_set_options_pattern() to simulate mount -a -O pattern
+- * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern
++ * mnt_context_set_options_pattern() to simulate mount -a -O pattern
++ * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern
+ *
+ * If the filesystem is already mounted or does not match defined criteria,
+ * then the mnt_context_next_mount() function returns zero, but the @ignored is
+@@ -1328,129 +1328,129 @@
+ * 1 at the end of the list.
+ */
+ int mnt_context_next_mount(struct libmnt_context *cxt,
+- struct libmnt_iter *itr,
+- struct libmnt_fs **fs,
+- int *mntrc,
+- int *ignored)
+-{
+- struct libmnt_table *fstab, *mtab;
+- const char *o, *tgt;
+- int rc, mounted = 0;
+-
+- if (ignored)
+- *ignored = 0;
+- if (mntrc)
+- *mntrc = 0;
+-
+- if (!cxt || !fs || !itr)
+- return -EINVAL;
+-
+- rc = mnt_context_get_fstab(cxt, &fstab);
+- if (rc)
+- return rc;
+-
+- rc = mnt_table_next_fs(fstab, itr, fs);
+- if (rc != 0)
+- return rc; /* more filesystems (or error) */
+-
+- o = mnt_fs_get_user_options(*fs);
+- tgt = mnt_fs_get_target(*fs);
+-
+- DBG(CXT, ul_debugobj(cxt, "next-mount: trying %s", tgt));
+-
+- /* ignore swap */
+- if (mnt_fs_is_swaparea(*fs) ||
+-
+- /* ignore root filesystem */
+- (tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 0)) ||
+-
+- /* ignore noauto filesystems */
+- (o && mnt_optstr_get_option(o, "noauto", NULL, NULL) == 0) ||
+-
+- /* ignore filesystems which don't match options patterns */
+- (cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
+- cxt->fstype_pattern)) ||
+-
+- /* ignore filesystems which don't match type patterns */
+- (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
+- cxt->optstr_pattern))) {
+- if (ignored)
+- *ignored = 1;
+- DBG(CXT, ul_debugobj(cxt, "next-mount: not-match "
+- "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
+- mnt_fs_get_fstype(*fs),
+- cxt->fstype_pattern,
+- mnt_fs_get_options(*fs),
+- cxt->optstr_pattern));
+- return 0;
+- }
+-
+- /* ignore already mounted filesystems */
+- rc = mnt_context_is_fs_mounted(cxt, *fs, &mounted);
+- if (rc)
+- return rc;
+- if (mounted) {
+- if (ignored)
+- *ignored = 2;
+- return 0;
+- }
+-
+- /* Save mount options, etc. -- this is effective for the first
+- * mnt_context_next_mount() call only. Make sure that cxt has not set
+- * source, target or fstype.
+- */
+- if (!mnt_context_has_template(cxt)) {
+- mnt_context_set_source(cxt, NULL);
+- mnt_context_set_target(cxt, NULL);
+- mnt_context_set_fstype(cxt, NULL);
+- mnt_context_save_template(cxt);
+- }
+-
+- /* reset context, but protect mtab */
+- mtab = cxt->mtab;
+- cxt->mtab = NULL;
+- mnt_reset_context(cxt);
+- cxt->mtab = mtab;
+-
+- if (mnt_context_is_fork(cxt)) {
+- rc = mnt_fork_context(cxt);
+- if (rc)
+- return rc; /* fork error */
+-
+- if (mnt_context_is_parent(cxt)) {
+- return 0; /* parent */
+- }
+- }
+-
+- /*
+- * child or non-forked
+- */
+-
+- /* copy stuff from fstab to context */
+- rc = mnt_context_apply_fs(cxt, *fs);
+- if (!rc) {
+- /*
+- * "-t <pattern>" is used to filter out fstab entries, but for ordinary
+- * mount operation -t means "-t <type>". We have to zeroize the pattern
+- * to avoid misinterpretation.
+- */
+- char *pattern = cxt->fstype_pattern;
+- cxt->fstype_pattern = NULL;
+-
+- rc = mnt_context_mount(cxt);
+-
+- cxt->fstype_pattern = pattern;
+-
+- if (mntrc)
+- *mntrc = rc;
+- }
+-
+- if (mnt_context_is_child(cxt)) {
+- DBG(CXT, ul_debugobj(cxt, "next-mount: child exit [rc=%d]", rc));
+- DBG_FLUSH;
+- _exit(rc);
+- }
+- return 0;
++ struct libmnt_iter *itr,
++ struct libmnt_fs **fs,
++ int *mntrc,
++ int *ignored)
++{
++ struct libmnt_table *fstab, *mtab;
++ const char *o, *tgt;
++ int rc, mounted = 0;
++
++ if (ignored)
++ *ignored = 0;
++ if (mntrc)
++ *mntrc = 0;
++
++ if (!cxt || !fs || !itr)
++ return -EINVAL;
++
++ rc = mnt_context_get_fstab(cxt, &fstab);
++ if (rc)
++ return rc;
++
++ rc = mnt_table_next_fs(fstab, itr, fs);
++ if (rc != 0)
++ return rc; /* more filesystems (or error) */
++
++ o = mnt_fs_get_user_options(*fs);
++ tgt = mnt_fs_get_target(*fs);
++
++ DBG(CXT, ul_debugobj(cxt, "next-mount: trying %s", tgt));
++
++ /* ignore swap */
++ if (mnt_fs_is_swaparea(*fs) ||
++
++ /* ignore root filesystem */
++ (tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 0)) ||
++
++ /* ignore noauto filesystems */
++ (o && mnt_optstr_get_option(o, "noauto", NULL, NULL) == 0) ||
++
++ /* ignore filesystems which don't match options patterns */
++ (cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
++ cxt->fstype_pattern)) ||
++
++ /* ignore filesystems which don't match type patterns */
++ (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
++ cxt->optstr_pattern))) {
++ if (ignored)
++ *ignored = 1;
++ DBG(CXT, ul_debugobj(cxt, "next-mount: not-match "
++ "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
++ mnt_fs_get_fstype(*fs),
++ cxt->fstype_pattern,
++ mnt_fs_get_options(*fs),
++ cxt->optstr_pattern));
++ return 0;
++ }
++
++ /* ignore already mounted filesystems */
++ rc = mnt_context_is_fs_mounted(cxt, *fs, &mounted);
++ if (rc)
++ return rc;
++ if (mounted) {
++ if (ignored)
++ *ignored = 2;
++ return 0;
++ }
++
++ /* Save mount options, etc. -- this is effective for the first
++ * mnt_context_next_mount() call only. Make sure that cxt has not set
++ * source, target or fstype.
++ */
++ if (!mnt_context_has_template(cxt)) {
++ mnt_context_set_source(cxt, NULL);
++ mnt_context_set_target(cxt, NULL);
++ mnt_context_set_fstype(cxt, NULL);
++ mnt_context_save_template(cxt);
++ }
++
++ /* reset context, but protect mtab */
++ mtab = cxt->mtab;
++ cxt->mtab = NULL;
++ mnt_reset_context(cxt);
++ cxt->mtab = mtab;
++
++ if (mnt_context_is_fork(cxt)) {
++ rc = mnt_fork_context(cxt);
++ if (rc)
++ return rc; /* fork error */
++
++ if (mnt_context_is_parent(cxt)) {
++ return 0; /* parent */
++ }
++ }
++
++ /*
++ * child or non-forked
++ */
++
++ /* copy stuff from fstab to context */
++ rc = mnt_context_apply_fs(cxt, *fs);
++ if (!rc) {
++ /*
++ * "-t <pattern>" is used to filter out fstab entries, but for ordinary
++ * mount operation -t means "-t <type>". We have to zeroize the pattern
++ * to avoid misinterpretation.
++ */
++ char *pattern = cxt->fstype_pattern;
++ cxt->fstype_pattern = NULL;
++
++ rc = mnt_context_mount(cxt);
++
++ cxt->fstype_pattern = pattern;
++
++ if (mntrc)
++ *mntrc = rc;
++ }
++
++ if (mnt_context_is_child(cxt)) {
++ DBG(CXT, ul_debugobj(cxt, "next-mount: child exit [rc=%d]", rc));
++ DBG_FLUSH;
++ _exit(rc);
++ }
++ return 0;
+ }
+
+
+@@ -1466,8 +1466,8 @@
+ * mnt_context_get_mtab()).
+ *
+ * You can filter out filesystems by:
+- * mnt_context_set_options_pattern() to simulate mount -a -O pattern
+- * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern
++ * mnt_context_set_options_pattern() to simulate mount -a -O pattern
++ * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern
+ *
+ * If the filesystem does not match defined criteria, then the
+ * mnt_context_next_remount() function returns zero, but the @ignored is
+@@ -1492,89 +1492,89 @@
+ * Since: 2.34
+ */
+ int mnt_context_next_remount(struct libmnt_context *cxt,
+- struct libmnt_iter *itr,
+- struct libmnt_fs **fs,
+- int *mntrc,
+- int *ignored)
+-{
+- struct libmnt_table *mtab;
+- const char *tgt;
+- int rc;
+-
+- if (ignored)
+- *ignored = 0;
+- if (mntrc)
+- *mntrc = 0;
+-
+- if (!cxt || !fs || !itr)
+- return -EINVAL;
+-
+- rc = mnt_context_get_mtab(cxt, &mtab);
+- if (rc)
+- return rc;
+-
+- rc = mnt_table_next_fs(mtab, itr, fs);
+- if (rc != 0)
+- return rc; /* more filesystems (or error) */
+-
+- tgt = mnt_fs_get_target(*fs);
+-
+- DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt));
+-
+- /* ignore filesystems which don't match options patterns */
+- if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
+- cxt->fstype_pattern)) ||
+-
+- /* ignore filesystems which don't match type patterns */
+- (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
+- cxt->optstr_pattern))) {
+- if (ignored)
+- *ignored = 1;
+- DBG(CXT, ul_debugobj(cxt, "next-remount: not-match "
+- "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
+- mnt_fs_get_fstype(*fs),
+- cxt->fstype_pattern,
+- mnt_fs_get_options(*fs),
+- cxt->optstr_pattern));
+- return 0;
+- }
+-
+- /* Save mount options, etc. -- this is effective for the first
+- * mnt_context_next_remount() call only. Make sure that cxt has not set
+- * source, target or fstype.
+- */
+- if (!mnt_context_has_template(cxt)) {
+- mnt_context_set_source(cxt, NULL);
+- mnt_context_set_target(cxt, NULL);
+- mnt_context_set_fstype(cxt, NULL);
+- mnt_context_save_template(cxt);
+- }
+-
+- /* restore original, but protect mtab */
+- cxt->mtab = NULL;
+- mnt_reset_context(cxt);
+- cxt->mtab = mtab;
+-
+- rc = mnt_context_set_target(cxt, tgt);
+- if (!rc) {
+- /*
+- * "-t <pattern>" is used to filter out fstab entries, but for ordinary
+- * mount operation -t means "-t <type>". We have to zeroize the pattern
+- * to avoid misinterpretation.
+- */
+- char *pattern = cxt->fstype_pattern;
+- cxt->fstype_pattern = NULL;
+-
+- rc = mnt_context_mount(cxt);
+-
+- cxt->fstype_pattern = pattern;
+-
+- if (mntrc)
+- *mntrc = rc;
+- rc = 0;
+- }
++ struct libmnt_iter *itr,
++ struct libmnt_fs **fs,
++ int *mntrc,
++ int *ignored)
++{
++ struct libmnt_table *mtab;
++ const char *tgt;
++ int rc;
++
++ if (ignored)
++ *ignored = 0;
++ if (mntrc)
++ *mntrc = 0;
++
++ if (!cxt || !fs || !itr)
++ return -EINVAL;
++
++ rc = mnt_context_get_mtab(cxt, &mtab);
++ if (rc)
++ return rc;
++
++ rc = mnt_table_next_fs(mtab, itr, fs);
++ if (rc != 0)
++ return rc; /* more filesystems (or error) */
++
++ tgt = mnt_fs_get_target(*fs);
++
++ DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt));
++
++ /* ignore filesystems which don't match options patterns */
++ if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
++ cxt->fstype_pattern)) ||
++
++ /* ignore filesystems which don't match type patterns */
++ (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
++ cxt->optstr_pattern))) {
++ if (ignored)
++ *ignored = 1;
++ DBG(CXT, ul_debugobj(cxt, "next-remount: not-match "
++ "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
++ mnt_fs_get_fstype(*fs),
++ cxt->fstype_pattern,
++ mnt_fs_get_options(*fs),
++ cxt->optstr_pattern));
++ return 0;
++ }
++
++ /* Save mount options, etc. -- this is effective for the first
++ * mnt_context_next_remount() call only. Make sure that cxt has not set
++ * source, target or fstype.
++ */
++ if (!mnt_context_has_template(cxt)) {
++ mnt_context_set_source(cxt, NULL);
++ mnt_context_set_target(cxt, NULL);
++ mnt_context_set_fstype(cxt, NULL);
++ mnt_context_save_template(cxt);
++ }
++
++ /* restore original, but protect mtab */
++ cxt->mtab = NULL;
++ mnt_reset_context(cxt);
++ cxt->mtab = mtab;
++
++ rc = mnt_context_set_target(cxt, tgt);
++ if (!rc) {
++ /*
++ * "-t <pattern>" is used to filter out fstab entries, but for ordinary
++ * mount operation -t means "-t <type>". We have to zeroize the pattern
++ * to avoid misinterpretation.
++ */
++ char *pattern = cxt->fstype_pattern;
++ cxt->fstype_pattern = NULL;
++
++ rc = mnt_context_mount(cxt);
++
++ cxt->fstype_pattern = pattern;
++
++ if (mntrc)
++ *mntrc = rc;
++ rc = 0;
++ }
+
+- return rc;
++ return rc;
+ }
+
+ /*
+@@ -1582,354 +1582,354 @@
+ */
+ static int is_shared_tree(struct libmnt_context *cxt, const char *dir)
+ {
+- struct libmnt_table *tb = NULL;
+- struct libmnt_fs *fs;
+- unsigned long mflags = 0;
+- char *mnt = NULL, *p;
+- int rc = 0;
+- struct libmnt_ns *ns_old;
+-
+- ns_old = mnt_context_switch_target_ns(cxt);
+- if (!ns_old)
+- return -MNT_ERR_NAMESPACE;
+-
+- if (!dir)
+- return 0;
+- if (mnt_context_get_mtab(cxt, &tb) || !tb)
+- goto done;
+-
+- mnt = strdup(dir);
+- if (!mnt)
+- goto done;
+- p = strrchr(mnt, '/');
+- if (!p)
+- goto done;
+- if (p > mnt)
+- *p = '\0';
+- fs = mnt_table_find_mountpoint(tb, mnt, MNT_ITER_BACKWARD);
+-
+- rc = fs && mnt_fs_is_kernel(fs)
+- && mnt_fs_get_propagation(fs, &mflags) == 0
+- && (mflags & MS_SHARED);
++ struct libmnt_table *tb = NULL;
++ struct libmnt_fs *fs;
++ unsigned long mflags = 0;
++ char *mnt = NULL, *p;
++ int rc = 0;
++ struct libmnt_ns *ns_old;
++
++ ns_old = mnt_context_switch_target_ns(cxt);
++ if (!ns_old)
++ return -MNT_ERR_NAMESPACE;
++
++ if (!dir)
++ return 0;
++ if (mnt_context_get_mtab(cxt, &tb) || !tb)
++ goto done;
++
++ mnt = strdup(dir);
++ if (!mnt)
++ goto done;
++ p = strrchr(mnt, '/');
++ if (!p)
++ goto done;
++ if (p > mnt)
++ *p = '\0';
++ fs = mnt_table_find_mountpoint(tb, mnt, MNT_ITER_BACKWARD);
++
++ rc = fs && mnt_fs_is_kernel(fs)
++ && mnt_fs_get_propagation(fs, &mflags) == 0
++ && (mflags & MS_SHARED);
+ done:
+- free(mnt);
+- if (!mnt_context_switch_ns(cxt, ns_old))
+- return -MNT_ERR_NAMESPACE;
+- return rc;
++ free(mnt);
++ if (!mnt_context_switch_ns(cxt, ns_old))
++ return -MNT_ERR_NAMESPACE;
++ return rc;
+ }
+
+ int mnt_context_get_mount_excode(
+- struct libmnt_context *cxt,
+- int rc,
+- char *buf,
+- size_t bufsz)
+-{
+- int syserr;
+- struct stat st;
+- unsigned long uflags = 0, mflags = 0;
+-
+- int restricted = mnt_context_is_restricted(cxt);
+- const char *tgt = mnt_context_get_target(cxt);
+- const char *src = mnt_context_get_source(cxt);
+-
+- if (mnt_context_helper_executed(cxt)) {
+- /*
+- * /sbin/mount.<type> called, return status
+- */
+- if (rc == -MNT_ERR_APPLYFLAGS && buf)
+- snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags"));
+-
+- return mnt_context_get_helper_status(cxt);
+- }
+-
+- if (rc == 0 && mnt_context_get_status(cxt) == 1) {
+- /*
+- * Libmount success && syscall success.
+- */
+- if (buf && mnt_context_forced_rdonly(cxt))
+- snprintf(buf, bufsz, _("WARNING: source write-protected, mounted read-only"));
+- return MNT_EX_SUCCESS;
+- }
+-
+- mnt_context_get_mflags(cxt, &mflags); /* mount(2) flags */
+- mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */
+-
+- if (!mnt_context_syscall_called(cxt)) {
+- /*
+- * libmount errors (extra library checks)
+- */
+- switch (rc) {
+- case -EPERM:
+- if (buf)
+- snprintf(buf, bufsz, _("operation permitted for root only"));
+- return MNT_EX_USAGE;
+- case -EBUSY:
+- if (buf)
+- snprintf(buf, bufsz, _("%s is already mounted"), src);
+- return MNT_EX_USAGE;
+- case -MNT_ERR_NOFSTAB:
+- if (!buf)
+- return MNT_EX_USAGE;
+- if (mnt_context_is_swapmatch(cxt))
+- snprintf(buf, bufsz, _("can't find in %s"),
+- mnt_get_fstab_path());
+- else if (tgt)
+- snprintf(buf, bufsz, _("can't find mount point in %s"),
+- mnt_get_fstab_path());
+- else if (src)
+- snprintf(buf, bufsz, _("can't find mount source %s in %s"),
+- src, mnt_get_fstab_path());
+- return MNT_EX_USAGE;
+- case -MNT_ERR_AMBIFS:
+- if (buf)
+- snprintf(buf, bufsz, _("more filesystems detected on %s; use -t <type> or wipefs(8)"), src);
+- return MNT_EX_USAGE;
+- case -MNT_ERR_NOFSTYPE:
+- if (buf)
+- snprintf(buf, bufsz, restricted ?
+- _("failed to determine filesystem type") :
+- _("no filesystem type specified"));
+- return MNT_EX_USAGE;
+- case -MNT_ERR_NOSOURCE:
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (buf) {
+- if (src)
+- snprintf(buf, bufsz, _("can't find %s"), src);
+- else
+- snprintf(buf, bufsz, _("no mount source specified"));
+- }
+- return MNT_EX_USAGE;
+- case -MNT_ERR_MOUNTOPT:
+- if (buf)
+- snprintf(buf, bufsz, errno ?
+- _("failed to parse mount options: %m") :
+- _("failed to parse mount options"));
+- return MNT_EX_USAGE;
+- case -MNT_ERR_LOOPDEV:
+- if (buf)
+- snprintf(buf, bufsz, _("failed to setup loop device for %s"), src);
+- return MNT_EX_FAIL;
+- case -MNT_ERR_LOOPOVERLAP:
+- if (buf)
+- snprintf(buf, bufsz, _("overlapping loop device exists for %s"), src);
+- return MNT_EX_FAIL;
+- case -MNT_ERR_LOCK:
+- if (buf)
+- snprintf(buf, bufsz, _("locking failed"));
+- return MNT_EX_FILEIO;
+- case -MNT_ERR_NAMESPACE:
+- if (buf)
+- snprintf(buf, bufsz, _("failed to switch namespace"));
+- return MNT_EX_SYSERR;
+- default:
+- return mnt_context_get_generic_excode(rc, buf, bufsz, _("mount failed: %m"));
+- }
+-
+- } else if (mnt_context_get_syscall_errno(cxt) == 0) {
+- /*
+- * mount(2) syscall success, but something else failed
+- * (probably error in mtab processing).
+- */
+- if (rc == -MNT_ERR_LOCK) {
+- if (buf)
+- snprintf(buf, bufsz, _("filesystem was mounted, but failed to update userspace mount table"));
+- return MNT_EX_FILEIO;
+- }
+-
+- if (rc == -MNT_ERR_NAMESPACE) {
+- if (buf)
+- snprintf(buf, bufsz, _("filesystem was mounted, but failed to switch namespace back"));
+- return MNT_EX_SYSERR;
+-
+- }
+-
+- if (rc < 0)
+- return mnt_context_get_generic_excode(rc, buf, bufsz,
+- _("filesystem was mounted, but any subsequent operation failed: %m"));
+-
+- return MNT_EX_SOFTWARE; /* internal error */
+-
+- }
+-
+- /*
+- * mount(2) errors
+- */
+- syserr = mnt_context_get_syscall_errno(cxt);
+-
+-
+- switch(syserr) {
+- case EPERM:
+- if (!buf)
+- break;
+- if (geteuid() == 0) {
+- if (mnt_stat_mountpoint(tgt, &st) || !S_ISDIR(st.st_mode))
+- snprintf(buf, bufsz, _("mount point is not a directory"));
+- else
+- snprintf(buf, bufsz, _("permission denied"));
+- } else
+- snprintf(buf, bufsz, _("must be superuser to use mount"));
+- break;
+-
+- case EBUSY:
+- if (!buf)
+- break;
+- if (mflags & MS_REMOUNT) {
+- snprintf(buf, bufsz, _("mount point is busy"));
+- break;
+- }
+- if (src) {
+- struct libmnt_fs *fs = get_already_mounted_source(cxt);
+-
+- if (fs && mnt_fs_get_target(fs))
+- snprintf(buf, bufsz, _("%s already mounted on %s"),
+- src, mnt_fs_get_target(fs));
+- }
+- if (!*buf)
+- snprintf(buf, bufsz, _("%s already mounted or mount point busy"), src);
+- break;
+- case ENOENT:
+- if (tgt && mnt_lstat_mountpoint(tgt, &st)) {
+- if (buf)
+- snprintf(buf, bufsz, _("mount point does not exist"));
+- } else if (tgt && mnt_stat_mountpoint(tgt, &st)) {
+- if (buf)
+- snprintf(buf, bufsz, _("mount point is a symbolic link to nowhere"));
+- } else if (src && stat(src, &st)) {
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (buf)
+- snprintf(buf, bufsz, _("special device %s does not exist"), src);
+- } else if (buf) {
+- errno = syserr;
+- snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
+- }
+- break;
+-
+- case ENOTDIR:
+- if (mnt_stat_mountpoint(tgt, &st) || ! S_ISDIR(st.st_mode)) {
+- if (buf)
+- snprintf(buf, bufsz, _("mount point is not a directory"));
+- } else if (src && stat(src, &st) && errno == ENOTDIR) {
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (buf)
+- snprintf(buf, bufsz, _("special device %s does not exist "
+- "(a path prefix is not a directory)"), src);
+- } else if (buf) {
+- errno = syserr;
+- snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
+- }
+- break;
+-
+- case EINVAL:
+- if (!buf)
+- break;
+- if (mflags & MS_REMOUNT)
+- snprintf(buf, bufsz, _("mount point not mounted or bad option"));
+- else if (rc == -MNT_ERR_APPLYFLAGS)
+- snprintf(buf, bufsz, _("not mount point or bad option"));
+- else if ((mflags & MS_MOVE) && is_shared_tree(cxt, src))
+- snprintf(buf, bufsz,
+- _("bad option; moving a mount "
+- "residing under a shared mount is unsupported"));
+- else if (mnt_fs_is_netfs(mnt_context_get_fs(cxt)))
+- snprintf(buf, bufsz,
+- _("bad option; for several filesystems (e.g. nfs, cifs) "
+- "you might need a /sbin/mount.<type> helper program"));
+- else
+- snprintf(buf, bufsz,
+- _("wrong fs type, bad option, bad superblock on %s, "
+- "missing codepage or helper program, or other error"),
+- src);
+- break;
+-
+- case EMFILE:
+- if (buf)
+- snprintf(buf, bufsz, _("mount table full"));
+- break;
+-
+- case EIO:
+- if (buf)
+- snprintf(buf, bufsz, _("can't read superblock on %s"), src);
+- break;
+-
+- case ENODEV:
+- if (!buf)
+- break;
+- if (mnt_context_get_fstype(cxt))
+- snprintf(buf, bufsz, _("unknown filesystem type '%s'"),
+- mnt_context_get_fstype(cxt));
+- else
+- snprintf(buf, bufsz, _("unknown filesystem type"));
+- break;
+-
+- case ENOTBLK:
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (!buf)
+- break;
+- if (src && stat(src, &st))
+- snprintf(buf, bufsz, _("%s is not a block device, and stat(2) fails?"), src);
+- else if (src && S_ISBLK(st.st_mode))
+- snprintf(buf, bufsz,
+- _("the kernel does not recognize %s as a block device; "
+- "maybe \"modprobe driver\" is necessary"), src);
+- else if (src && S_ISREG(st.st_mode))
+- snprintf(buf, bufsz, _("%s is not a block device; try \"-o loop\""), src);
+- else
+- snprintf(buf, bufsz, _("%s is not a block device"), src);
+- break;
+-
+- case ENXIO:
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (buf)
+- snprintf(buf, bufsz, _("%s is not a valid block device"), src);
+- break;
+-
+- case EACCES:
+- case EROFS:
+- if (!buf)
+- break;
+- if (mflags & MS_RDONLY)
+- snprintf(buf, bufsz, _("cannot mount %s read-only"), src);
+- else if (mnt_context_is_rwonly_mount(cxt))
+- snprintf(buf, bufsz, _("%s is write-protected but explicit read-write mode requested"), src);
+- else if (mflags & MS_REMOUNT)
+- snprintf(buf, bufsz, _("cannot remount %s read-write, is write-protected"), src);
+- else if (mflags & MS_BIND)
+- snprintf(buf, bufsz, _("bind %s failed"), src);
+- else {
+- errno = syserr;
+- snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
+- }
+- break;
+-
+- case ENOMEDIUM:
+- if (uflags & MNT_MS_NOFAIL)
+- return MNT_EX_SUCCESS;
+- if (buf)
+- snprintf(buf, bufsz, _("no medium found on %s"), src);
+- break;
+-
+- case EBADMSG:
+- /* Bad CRC for classic filesystems (e.g. extN or XFS) */
+- if (buf && src && stat(src, &st) == 0
+- && (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode))) {
+- snprintf(buf, bufsz, _("cannot mount; probably corrupted filesystem on %s"), src);
+- break;
+- }
+- /* fallthrough */
+-
+- default:
+- if (buf) {
+- errno = syserr;
+- snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
+- }
+- break;
+- }
++ struct libmnt_context *cxt,
++ int rc,
++ char *buf,
++ size_t bufsz)
++{
++ int syserr;
++ struct stat st;
++ unsigned long uflags = 0, mflags = 0;
++
++ int restricted = mnt_context_is_restricted(cxt);
++ const char *tgt = mnt_context_get_target(cxt);
++ const char *src = mnt_context_get_source(cxt);
++
++ if (mnt_context_helper_executed(cxt)) {
++ /*
++ * /sbin/mount.<type> called, return status
++ */
++ if (rc == -MNT_ERR_APPLYFLAGS && buf)
++ snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags"));
++
++ return mnt_context_get_helper_status(cxt);
++ }
++
++ if (rc == 0 && mnt_context_get_status(cxt) == 1) {
++ /*
++ * Libmount success && syscall success.
++ */
++ if (buf && mnt_context_forced_rdonly(cxt))
++ snprintf(buf, bufsz, _("WARNING: source write-protected, mounted read-only"));
++ return MNT_EX_SUCCESS;
++ }
++
++ mnt_context_get_mflags(cxt, &mflags); /* mount(2) flags */
++ mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */
++
++ if (!mnt_context_syscall_called(cxt)) {
++ /*
++ * libmount errors (extra library checks)
++ */
++ switch (rc) {
++ case -EPERM:
++ if (buf)
++ snprintf(buf, bufsz, _("operation permitted for root only"));
++ return MNT_EX_USAGE;
++ case -EBUSY:
++ if (buf)
++ snprintf(buf, bufsz, _("%s is already mounted"), src);
++ return MNT_EX_USAGE;
++ case -MNT_ERR_NOFSTAB:
++ if (!buf)
++ return MNT_EX_USAGE;
++ if (mnt_context_is_swapmatch(cxt))
++ snprintf(buf, bufsz, _("can't find in %s"),
++ mnt_get_fstab_path());
++ else if (tgt)
++ snprintf(buf, bufsz, _("can't find mount point in %s"),
++ mnt_get_fstab_path());
++ else if (src)
++ snprintf(buf, bufsz, _("can't find mount source %s in %s"),
++ src, mnt_get_fstab_path());
++ return MNT_EX_USAGE;
++ case -MNT_ERR_AMBIFS:
++ if (buf)
++ snprintf(buf, bufsz, _("more filesystems detected on %s; use -t <type> or wipefs(8)"), src);
++ return MNT_EX_USAGE;
++ case -MNT_ERR_NOFSTYPE:
++ if (buf)
++ snprintf(buf, bufsz, restricted ?
++ _("failed to determine filesystem type") :
++ _("no filesystem type specified"));
++ return MNT_EX_USAGE;
++ case -MNT_ERR_NOSOURCE:
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (buf) {
++ if (src)
++ snprintf(buf, bufsz, _("can't find %s"), src);
++ else
++ snprintf(buf, bufsz, _("no mount source specified"));
++ }
++ return MNT_EX_USAGE;
++ case -MNT_ERR_MOUNTOPT:
++ if (buf)
++ snprintf(buf, bufsz, errno ?
++ _("failed to parse mount options: %m") :
++ _("failed to parse mount options"));
++ return MNT_EX_USAGE;
++ case -MNT_ERR_LOOPDEV:
++ if (buf)
++ snprintf(buf, bufsz, _("failed to setup loop device for %s"), src);
++ return MNT_EX_FAIL;
++ case -MNT_ERR_LOOPOVERLAP:
++ if (buf)
++ snprintf(buf, bufsz, _("overlapping loop device exists for %s"), src);
++ return MNT_EX_FAIL;
++ case -MNT_ERR_LOCK:
++ if (buf)
++ snprintf(buf, bufsz, _("locking failed"));
++ return MNT_EX_FILEIO;
++ case -MNT_ERR_NAMESPACE:
++ if (buf)
++ snprintf(buf, bufsz, _("failed to switch namespace"));
++ return MNT_EX_SYSERR;
++ default:
++ return mnt_context_get_generic_excode(rc, buf, bufsz, _("mount failed: %m"));
++ }
++
++ } else if (mnt_context_get_syscall_errno(cxt) == 0) {
++ /*
++ * mount(2) syscall success, but something else failed
++ * (probably error in mtab processing).
++ */
++ if (rc == -MNT_ERR_LOCK) {
++ if (buf)
++ snprintf(buf, bufsz, _("filesystem was mounted, but failed to update userspace mount table"));
++ return MNT_EX_FILEIO;
++ }
++
++ if (rc == -MNT_ERR_NAMESPACE) {
++ if (buf)
++ snprintf(buf, bufsz, _("filesystem was mounted, but failed to switch namespace back"));
++ return MNT_EX_SYSERR;
++
++ }
++
++ if (rc < 0)
++ return mnt_context_get_generic_excode(rc, buf, bufsz,
++ _("filesystem was mounted, but any subsequent operation failed: %m"));
++
++ return MNT_EX_SOFTWARE; /* internal error */
++
++ }
++
++ /*
++ * mount(2) errors
++ */
++ syserr = mnt_context_get_syscall_errno(cxt);
++
++
++ switch(syserr) {
++ case EPERM:
++ if (!buf)
++ break;
++ if (geteuid() == 0) {
++ if (mnt_stat_mountpoint(tgt, &st) || !S_ISDIR(st.st_mode))
++ snprintf(buf, bufsz, _("mount point is not a directory"));
++ else
++ snprintf(buf, bufsz, _("permission denied"));
++ } else
++ snprintf(buf, bufsz, _("must be superuser to use mount"));
++ break;
++
++ case EBUSY:
++ if (!buf)
++ break;
++ if (mflags & MS_REMOUNT) {
++ snprintf(buf, bufsz, _("mount point is busy"));
++ break;
++ }
++ if (src) {
++ struct libmnt_fs *fs = get_already_mounted_source(cxt);
++
++ if (fs && mnt_fs_get_target(fs))
++ snprintf(buf, bufsz, _("%s already mounted on %s"),
++ src, mnt_fs_get_target(fs));
++ }
++ if (!*buf)
++ snprintf(buf, bufsz, _("%s already mounted or mount point busy"), src);
++ break;
++ case ENOENT:
++ if (tgt && mnt_lstat_mountpoint(tgt, &st)) {
++ if (buf)
++ snprintf(buf, bufsz, _("mount point does not exist"));
++ } else if (tgt && mnt_stat_mountpoint(tgt, &st)) {
++ if (buf)
++ snprintf(buf, bufsz, _("mount point is a symbolic link to nowhere"));
++ } else if (src && stat(src, &st)) {
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (buf)
++ snprintf(buf, bufsz, _("special device %s does not exist"), src);
++ } else if (buf) {
++ errno = syserr;
++ snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
++ }
++ break;
++
++ case ENOTDIR:
++ if (mnt_stat_mountpoint(tgt, &st) || ! S_ISDIR(st.st_mode)) {
++ if (buf)
++ snprintf(buf, bufsz, _("mount point is not a directory"));
++ } else if (src && stat(src, &st) && errno == ENOTDIR) {
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (buf)
++ snprintf(buf, bufsz, _("special device %s does not exist "
++ "(a path prefix is not a directory)"), src);
++ } else if (buf) {
++ errno = syserr;
++ snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
++ }
++ break;
++
++ case EINVAL:
++ if (!buf)
++ break;
++ if (mflags & MS_REMOUNT)
++ snprintf(buf, bufsz, _("mount point not mounted or bad option"));
++ else if (rc == -MNT_ERR_APPLYFLAGS)
++ snprintf(buf, bufsz, _("not mount point or bad option"));
++ else if ((mflags & MS_MOVE) && is_shared_tree(cxt, src))
++ snprintf(buf, bufsz,
++ _("bad option; moving a mount "
++ "residing under a shared mount is unsupported"));
++ else if (mnt_fs_is_netfs(mnt_context_get_fs(cxt)))
++ snprintf(buf, bufsz,
++ _("bad option; for several filesystems (e.g. nfs, cifs) "
++ "you might need a /sbin/mount.<type> helper program"));
++ else
++ snprintf(buf, bufsz,
++ _("wrong fs type, bad option, bad superblock on %s, "
++ "missing codepage or helper program, or other error"),
++ src);
++ break;
++
++ case EMFILE:
++ if (buf)
++ snprintf(buf, bufsz, _("mount table full"));
++ break;
++
++ case EIO:
++ if (buf)
++ snprintf(buf, bufsz, _("can't read superblock on %s"), src);
++ break;
++
++ case ENODEV:
++ if (!buf)
++ break;
++ if (mnt_context_get_fstype(cxt))
++ snprintf(buf, bufsz, _("unknown filesystem type '%s'"),
++ mnt_context_get_fstype(cxt));
++ else
++ snprintf(buf, bufsz, _("unknown filesystem type"));
++ break;
++
++ case ENOTBLK:
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (!buf)
++ break;
++ if (src && stat(src, &st))
++ snprintf(buf, bufsz, _("%s is not a block device, and stat(2) fails?"), src);
++ else if (src && S_ISBLK(st.st_mode))
++ snprintf(buf, bufsz,
++ _("the kernel does not recognize %s as a block device; "
++ "maybe \"modprobe driver\" is necessary"), src);
++ else if (src && S_ISREG(st.st_mode))
++ snprintf(buf, bufsz, _("%s is not a block device; try \"-o loop\""), src);
++ else
++ snprintf(buf, bufsz, _("%s is not a block device"), src);
++ break;
++
++ case ENXIO:
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (buf)
++ snprintf(buf, bufsz, _("%s is not a valid block device"), src);
++ break;
++
++ case EACCES:
++ case EROFS:
++ if (!buf)
++ break;
++ if (mflags & MS_RDONLY)
++ snprintf(buf, bufsz, _("cannot mount %s read-only"), src);
++ else if (mnt_context_is_rwonly_mount(cxt))
++ snprintf(buf, bufsz, _("%s is write-protected but explicit read-write mode requested"), src);
++ else if (mflags & MS_REMOUNT)
++ snprintf(buf, bufsz, _("cannot remount %s read-write, is write-protected"), src);
++ else if (mflags & MS_BIND)
++ snprintf(buf, bufsz, _("bind %s failed"), src);
++ else {
++ errno = syserr;
++ snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
++ }
++ break;
++
++ case ENOMEDIUM:
++ if (uflags & MNT_MS_NOFAIL)
++ return MNT_EX_SUCCESS;
++ if (buf)
++ snprintf(buf, bufsz, _("no medium found on %s"), src);
++ break;
++
++ case EBADMSG:
++ /* Bad CRC for classic filesystems (e.g. extN or XFS) */
++ if (buf && src && stat(src, &st) == 0
++ && (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode))) {
++ snprintf(buf, bufsz, _("cannot mount; probably corrupted filesystem on %s"), src);
++ break;
++ }
++ /* fallthrough */
++
++ default:
++ if (buf) {
++ errno = syserr;
++ snprintf(buf, bufsz, _("mount(2) system call failed: %m"));
++ }
++ break;
++ }
+
+- return MNT_EX_FAIL;
++ return MNT_EX_FAIL;
+ }
+
diff --git a/60-rfkill.rules b/60-rfkill.rules
new file mode 100644
index 00000000000..bc98a3bef78
--- /dev/null
+++ b/60-rfkill.rules
@@ -0,0 +1 @@
+KERNEL=="rfkill", GROUP="rfkill", MODE="0664"
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 00000000000..d9a5e96478f
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,185 @@
+# Maintainer : Vincent Grande <shoober420@gmail.com>
+# Contributor : Eric Vidal <eric@obarun.org>
+# Contributor : Jean-Michel T.Dydak <jean-michel@obarun.org>
+# Obarun PkgSrc : https://framagit.org/pkg/obcore/util-linux/
+#----------------
+# Contributor : Tom Gundersen <teg@jklm.no>
+# Contributor : Dave Reisner <dreisner@archlinux.org>
+# Contributor : judd <jvinet@zeroflux.org>
+# Arch PkrSrc : https://www.archlinux.org/packages/core/x86_64/util-linux/
+#---------------------------------------------------------------------------
+# Website : https://www.kernel.org/pub/linux/utils/util-linux/
+#---------------------------------------------------------------------------
+#--DESCRIPTION--------------------------------------------------------------
+
+pkgname=(util-linux-nosystemd-minimal-git util-linux-libs-nosystemd-minimal-git)
+
+pkgdesc="Miscellaneous system utilities for Linux"
+
+pkgver=2.36.1
+pkgrel=1
+
+url='https://www.kernel.org/pub/linux/utils/util-linux'
+
+source=("git+https://github.com/karelzak/util-linux.git"
+ 'pam-login'
+ 'pam-common'
+ 'pam-runuser'
+ 'pam-su'
+ '60-rfkill.rules'
+ 'util-linux.sysusers'
+ '0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch')
+
+#--BUILD CONFIGURATION------------------------------------------------------
+
+options=(
+ 'strip')
+
+makedepends=(
+ 'python'
+ 'libcap-ng'
+ 'libxcrypt')
+
+#--BUILD PREPARATION--------------------------------------------------------
+
+pkgver() {
+ cd util-linux
+ git describe --tags | sed 's/-/+/g'
+}
+
+prepare() {
+ cd "$pkgbase-$pkgver"
+
+ patch -Np1 < ../0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch
+}
+
+#--BUILD CONTROL------------------------------------------------------------
+
+path=(
+ --prefix=/usr
+ --libdir=/usr/lib
+ --bindir=/usr/bin
+ --sbindir=/usr/bin
+ --localstatedir=/var
+)
+
+flags=(
+ --enable-usrdir-path
+ --enable-fs-paths-default=/usr/bin:/usr/local/bin
+ --enable-raw
+ --enable-vipw
+ --enable-newgrp
+ --enable-chfn-chsh
+ --enable-write
+ --enable-mesg
+ --with-python=3
+ --disable-hardlink
+ --with-systemdsystemunitdir=no
+ --with-systemd=no
+ --with-selinux=no
+ --with-audit=no
+)
+
+#--BUILD--------------------------------------------------------------------
+
+build() {
+ cd util-linux
+
+ ./autogen.sh
+ ./configure "${path[@]}" "${flags[@]}"
+ make
+}
+
+#--CHECK--------------------------------------------------------------------
+
+
+#--PACKAGE------------------------------------------------------------------
+
+package_util-linux-nosystemd-minimal-git() {
+ conflicts=('rfkill' 'util-linux')
+ provides=('rfkill' 'util-linux')
+ replaces=('rfkill')
+ depends=(
+ 'pam'
+ 'shadow'
+ 'coreutils'
+ 'libutil-linux'
+ 'libeudev'
+ 'libcap-ng'
+ 'libxcrypt'
+ 'libcrypt.so'
+ 'libmagic.so'
+ 'libncursesw.so'
+ 'libreadline.so'
+ )
+ optdepends=('python: python bindings to libmount'
+ 'words: default dictionary for look')
+ groups=('base' 'base-devel')
+ backup=(etc/pam.d/chfn
+ etc/pam.d/chsh
+ etc/pam.d/login
+ etc/pam.d/runuser
+ etc/pam.d/runuser-l
+ etc/pam.d/su
+ etc/pam.d/su-l)
+
+ cd util-linux
+
+ make DESTDIR="$pkgdir" install
+
+ ## setuid chfn and chsh
+ chmod 4755 "$pkgdir"/usr/bin/{newgrp,ch{sh,fn}}
+
+ ## install PAM files for login-utils
+ install -Dm 0644 "$srcdir/pam-common" "$pkgdir/etc/pam.d/chfn"
+ install -m 0644 "$srcdir/pam-common" "$pkgdir/etc/pam.d/chsh"
+ install -m 0644 "$srcdir/pam-login" "$pkgdir/etc/pam.d/login"
+ install -m 0644 "$srcdir/pam-runuser" "$pkgdir/etc/pam.d/runuser"
+ install -m 0644 "$srcdir/pam-runuser" "$pkgdir/etc/pam.d/runuser-l"
+ install -m 0644 "$srcdir/pam-su" "$pkgdir/etc/pam.d/su"
+ install -m 0644 "$srcdir/pam-su" "$pkgdir/etc/pam.d/su-l"
+
+ ## adjust for usrmove
+ ## TODO(dreisner): fix configure.ac upstream so that this isn't needed
+ cd "$pkgdir"
+ mv usr/sbin/* usr/bin
+ rmdir usr/sbin
+
+ ### runtime libs are shipped as part of util-linux-libs
+ rm "$pkgdir"/usr/lib/lib*.{a,so}*
+
+ ### install pacopts applysys
+ install -Dm 0644 "$srcdir/util-linux.sysusers" \
+ "$pkgdir/usr/lib/sysusers.d/util-linux.conf"
+
+ install -Dm 0644 "$srcdir/60-rfkill.rules" \
+ "$pkgdir/usr/lib/udev/rules.d/60-rfkill.rules"
+}
+
+package_util-linux-libs-nosystemd-minimal-git() {
+ pkgdesc="util-linux runtime libraries"
+ provides=('util-linux-libs' 'libutil-linux' 'libblkid.so' 'libfdisk.so' 'libmount.so' 'libsmartcols.so' 'libuuid.so')
+ conflicts=('libutil-linux' 'util-linux-libs')
+ replaces=('libutil-linux')
+
+ make -C util-linux DESTDIR="$pkgdir" install-usrlib_execLTLIBRARIES
+}
+
+#--INSTALL CONFIGURATION----------------------------------------------------
+
+arch=('x86_64')
+
+#--SECURITY AND LICENCE-----------------------------------------------------
+
+license=('GPL2')
+
+#validpgpkeys=('B0C64D14301CC6EFAEDF60E4E4B71D5EEC39C284') # Karel Zak
+
+sha256sums=('SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP')
diff --git a/pam-common b/pam-common
new file mode 100644
index 00000000000..a7bf8a4a5b0
--- /dev/null
+++ b/pam-common
@@ -0,0 +1,6 @@
+#%PAM-1.0
+auth sufficient pam_rootok.so
+auth required pam_unix.so
+account required pam_unix.so
+session required pam_unix.so
+password required pam_permit.so
diff --git a/pam-login b/pam-login
new file mode 100644
index 00000000000..1960d9497c0
--- /dev/null
+++ b/pam-login
@@ -0,0 +1,7 @@
+#%PAM-1.0
+
+auth required pam_securetty.so
+auth requisite pam_nologin.so
+auth include system-local-login
+account include system-local-login
+session include system-local-login
diff --git a/pam-runuser b/pam-runuser
new file mode 100644
index 00000000000..2eba78acdb2
--- /dev/null
+++ b/pam-runuser
@@ -0,0 +1,4 @@
+#%PAM-1.0
+
+auth sufficient pam_rootok.so
+session include system-login
diff --git a/pam-su b/pam-su
new file mode 100644
index 00000000000..cf15f40f1ae
--- /dev/null
+++ b/pam-su
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth sufficient pam_rootok.so
+# Uncomment the following line to implicitly trust users in the "wheel" group.
+#auth sufficient pam_wheel.so trust use_uid
+# Uncomment the following line to require a user to be in the "wheel" group.
+#auth required pam_wheel.so use_uid
+auth required pam_unix.so
+account required pam_unix.so
+session required pam_unix.so
diff --git a/util-linux.sysusers b/util-linux.sysusers
new file mode 100644
index 00000000000..56411a85231
--- /dev/null
+++ b/util-linux.sysusers
@@ -0,0 +1,3 @@
+u uuidd 68
+g rfkill - - -
+