summaryrefslogtreecommitdiff
path: root/testing/util-linux
diff options
context:
space:
mode:
authorroot <root@rshg054.dnsready.net>2012-03-15 00:01:19 +0000
committerroot <root@rshg054.dnsready.net>2012-03-15 00:01:19 +0000
commit14635ca5380a480450a66c3fcc29992d29a2bd8e (patch)
treea2f8e712c9e15b829397666c06d1cdd1a877d8a6 /testing/util-linux
parent01a0c4bc740842efa3bf1a7e1d6c8be5656e4e2a (diff)
Thu Mar 15 00:01:19 UTC 2012
Diffstat (limited to 'testing/util-linux')
-rw-r--r--testing/util-linux/PKGBUILD28
-rw-r--r--testing/util-linux/stable-fixes-2.21.patch1516
2 files changed, 1522 insertions, 22 deletions
diff --git a/testing/util-linux/PKGBUILD b/testing/util-linux/PKGBUILD
index c8d71e48e..2daf29ea4 100644
--- a/testing/util-linux/PKGBUILD
+++ b/testing/util-linux/PKGBUILD
@@ -1,10 +1,10 @@
-# $Id: PKGBUILD 151651 2012-02-29 16:49:07Z tomegun $
+# $Id: PKGBUILD 153424 2012-03-13 15:26:09Z tomegun $
# Maintainer: Tom Gundersen <teg@jklm.no>
# Contributor: judd <jvinet@zeroflux.org>
pkgname=util-linux
pkgver=2.21
-pkgrel=4
+pkgrel=5
pkgdesc="Miscellaneous system utilities for Linux"
url="http://www.kernel.org/pub/linux/utils/util-linux/"
arch=('i686' 'x86_64')
@@ -15,12 +15,7 @@ provides=("util-linux-ng=${pkgver}")
license=('GPL2')
options=('!libtool')
source=(ftp://ftp.kernel.org/pub/linux/utils/${pkgname}/v${pkgver}/${pkgname}-${pkgver}.tar.xz
- libmount-canonicalize-all-paths-from-fs-tab.patch
- lib-canonicalize-always-remove-tailing-slash.patch
- libmount-canonicalize-targets-from-fstab-on-mount-a.patch
- mount-new-cleanup-mount-a-return-codes.patch
- libmount-use-mount.-type-s-for-NFS-only.patch
- libmount-allow-empty-source-for-mount-2-syscall.patch)
+ stable-fixes-2.21.patch)
optdepends=('perl: for chkdupexe support')
build() {
@@ -29,19 +24,13 @@ build() {
# hardware clock
sed -e 's%etc/adjtime%var/lib/hwclock/adjtime%' -i include/pathnames.h
- patch -p1 -i ../libmount-canonicalize-all-paths-from-fs-tab.patch
- patch -p1 -i ../lib-canonicalize-always-remove-tailing-slash.patch
- patch -p1 -i ../libmount-canonicalize-targets-from-fstab-on-mount-a.patch
- patch -p1 -i ../mount-new-cleanup-mount-a-return-codes.patch
- patch -p1 -i ../libmount-use-mount.-type-s-for-NFS-only.patch
- patch -p1 -i ../libmount-allow-empty-source-for-mount-2-syscall.patch
+ patch -p1 -i ../stable-fixes-2.21.patch
./configure --prefix=/usr \
--libdir=/usr/lib \
--enable-write \
--enable-raw \
- --disable-wall \
- --enable-new-mount
+ --disable-wall
make
}
@@ -59,9 +48,4 @@ package() {
rm -r usr/share/man/ru
}
md5sums=('208aa058f4117759d2939d1be7d662fc'
- 'c4011222a19b020d9b8465c3c7e443f6'
- '8c1bf7b10e22e2b835441e6ae2d804d6'
- '7b92423c588ed35229a9a166349c29a9'
- 'c483ab2d52609b5857d096b256a5075c'
- 'e31037773db7f3244b71db434f60e6f0'
- '2de5ae7916e79970e90bf06542e43d86')
+ '415b850a4efa9174cd9c34022949f177')
diff --git a/testing/util-linux/stable-fixes-2.21.patch b/testing/util-linux/stable-fixes-2.21.patch
new file mode 100644
index 000000000..3c6c32483
--- /dev/null
+++ b/testing/util-linux/stable-fixes-2.21.patch
@@ -0,0 +1,1516 @@
+diff --git a/configure.ac b/configure.ac
+index d3b298c..9da5b24 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -387,6 +387,8 @@ AC_CACHE_VAL([scanf_cv_alloc_modifier],
+ [scanf_cv_alloc_modifier=as],
+ [scanf_cv_alloc_modifier=no]
+ )
++ ,
++ [scanf_cv_alloc_modifier=no]
+ )
+ )
+
+@@ -833,6 +835,8 @@ AC_ARG_ENABLE([ddate],
+ )
+ UL_BUILD_INIT([ddate])
+ AM_CONDITIONAL(BUILD_DDATE, test "x$build_ddate" = xyes)
++ruman1dir='${mandir}/ru/man1'
++AC_SUBST([ruman1dir])
+
+
+ AC_ARG_ENABLE([agetty],
+diff --git a/fdisk/fdiskbsdlabel.h b/fdisk/fdiskbsdlabel.h
+index 9f9e091..e58e2ff 100644
+--- a/fdisk/fdiskbsdlabel.h
++++ b/fdisk/fdiskbsdlabel.h
+@@ -46,7 +46,7 @@
+
+ #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
+
+-#if defined (i386) || defined (__sparc__) || defined (__arm__) || \
++#if defined (__i386__) || defined (__sparc__) || defined (__arm__) || \
+ defined (__mips__) || defined (__s390__) || defined (__sh__) || \
+ defined(__x86_64__) || defined (__avr32__) || defined(__cris__)
+ #define BSD_LABELSECTOR 1
+diff --git a/include/list.h b/include/list.h
+index 3ce46ca..d8c3bf0 100644
+--- a/include/list.h
++++ b/include/list.h
+@@ -166,6 +166,10 @@ _INLINE_ void list_splice(struct list_head *list, struct list_head *head)
+ #define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
++
++#define list_first_entry(head, type, member) \
++ ((head) && (head)->next != (head) ? list_entry((head)->next, type, member) : NULL)
++
+ /**
+ * list_for_each - iterate over elements in a list
+ * @pos: the &struct list_head to use as a loop counter.
+diff --git a/lib/canonicalize.c b/lib/canonicalize.c
+index ab32c10..fd18af4 100644
+--- a/lib/canonicalize.c
++++ b/lib/canonicalize.c
+@@ -174,9 +174,16 @@ canonicalize_path(const char *path)
+ if (path == NULL)
+ return NULL;
+
+- if (!myrealpath(path, canonical, PATH_MAX+1))
+- return strdup(path);
+-
++ if (!myrealpath(path, canonical, PATH_MAX+1)) {
++ char *res = strdup(path);
++ if (res) {
++ p = strrchr(res, '/');
++ /* delete trailing slash */
++ if (p && p > res && *(p + 1) == '\0')
++ *p = '\0';
++ }
++ return res;
++ }
+
+ p = strrchr(canonical, '/');
+ if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
+diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c
+index 763f75c..6bd69d3 100644
+--- a/libblkid/src/probe.c
++++ b/libblkid/src/probe.c
+@@ -388,6 +388,7 @@ void blkid_reset_probe(blkid_probe pr)
+ return;
+
+ blkid_probe_reset_vals(pr);
++ blkid_probe_set_wiper(pr, 0, 0);
+
+ pr->cur_chain = NULL;
+
+@@ -989,7 +990,7 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
+ len = sizeof(buf);
+
+ DBG(DEBUG_LOWPROBE, printf(
+- "wiping [offset=0x%jx, len=%zd, chain=%s, idx=%d, dryrun=%s]\n",
++ "do_wipe [offset=0x%jx, len=%zd, chain=%s, idx=%d, dryrun=%s]\n",
+ offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
+
+ l = lseek(fd, offset, SEEK_SET);
+@@ -1008,10 +1009,23 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
+ if (chn->idx >= 0) {
+ chn->idx--;
+ DBG(DEBUG_LOWPROBE,
+- printf("wipe: moving %s chain index to %d\n",
++ printf("do_wipe: moving %s chain index to %d\n",
+ chn->driver->name,
+ chn->idx));
+ }
++ if (chn->idx == -1) {
++ /* blkid_do_probe() goes to the next chain if the index
++ * of the current chain is -1, so we have to set the
++ * chain pointer to the previos chain.
++ */
++ size_t idx = chn->driver->id > 0 ?
++ chn->driver->id - 1 : 0;
++
++ if (idx > 0)
++ pr->cur_chain = &pr->chains[idx];
++ else if (idx == 0)
++ pr->cur_chain = NULL;
++ }
+ }
+ return 0;
+ }
+@@ -1579,8 +1593,9 @@ size_t blkid_rtrim_whitespace(unsigned char *str)
+ * for later resolution to conflicts between superblocks.
+ *
+ * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
+- * the device. If we found another signature (for example MBR) this wiped area
+- * then the signature has been added later and LVM superblock should be ignore.
++ * the device. If we found another signature (for example MBR) within the
++ * wiped area then the signature has been added later and LVM superblock
++ * should be ignore.
+ *
+ * Note that this heuristic is not 100% reliable, for example "pvcreate --zero
+ * n" allows to keep the begin of the device unmodified. It's probably better
+@@ -1588,6 +1603,16 @@ size_t blkid_rtrim_whitespace(unsigned char *str)
+ * than for conflicts between filesystem superblocks -- existence of unwanted
+ * partition table is very unusual, because PT is pretty visible (parsed and
+ * interpreted by kernel).
++ *
++ * Note that we usually expect only one signature on the device, it means that
++ * we have to remember only one wiped area from previously successfully
++ * detected signature.
++ *
++ * blkid_probe_set_wiper() -- defines wiped area (e.g. LVM)
++ * blkid_probe_use_wiper() -- try to use area (e.g. MBR)
++ *
++ * Note that there is not relation between _wiper and blkid_to_wipe().
++ *
+ */
+ void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
+ {
+@@ -1638,12 +1663,17 @@ int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
+ return 0;
+ }
+
++/*
++ * Try to use any area -- if the area has been previously wiped then the
++ * previous probing result should be ignored (reseted).
++ */
+ void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
+ {
+ struct blkid_chain *chn = NULL;
+
+ if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
+- DBG(DEBUG_LOWPROBE, printf("wiped area detected -- ignore previous results\n"));
++ DBG(DEBUG_LOWPROBE, printf("previously wiped area modified "
++ " -- ignore previous results\n"));
+ blkid_probe_set_wiper(pr, 0, 0);
+ blkid_probe_chain_reset_vals(pr, chn);
+ }
+diff --git a/libmount/src/context.c b/libmount/src/context.c
+index 1f30292..f97dd36 100644
+--- a/libmount/src/context.c
++++ b/libmount/src/context.c
+@@ -1165,6 +1165,10 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
+
+ src = mnt_fs_get_source(cxt->fs);
+
++ if (!src && (cxt->mountflags & MS_PROPAGATION))
++ /* mount --make-{shared,private,...} */
++ return mnt_fs_set_source(cxt->fs, "none");
++
+ /* ignore filesystems without source or filesystems
+ * where the source is quasi-path (//foo/bar)
+ */
+@@ -1203,7 +1207,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
+
+ if ((cxt->mountflags & (MS_BIND | MS_MOVE | MS_PROPAGATION)) ||
+ mnt_fs_is_pseudofs(cxt->fs)) {
+- DBG(CXT, mnt_debug_h(cxt, "PROPAGATION/pseudo FS source: %s", path));
++ DBG(CXT, mnt_debug_h(cxt, "BIND/MOVE/pseudo FS source: %s", path));
+ return rc;
+ }
+
+diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
+index 8cbc25b..c56ffd4 100644
+--- a/libmount/src/context_mount.c
++++ b/libmount/src/context_mount.c
+@@ -369,7 +369,12 @@ static int exec_helper(struct libmnt_context *cxt)
+ args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */
+ args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */
+
+- if (mnt_context_is_sloppy(cxt))
++ /*
++ * TODO: remove the exception for "nfs", -s is documented
++ * for years should be usable everywhere.
++ */
++ if (mnt_context_is_sloppy(cxt) &&
++ type && startswith(type, "nfs"))
+ args[i++] = "-s"; /* 4 */
+ if (mnt_context_is_fake(cxt))
+ args[i++] = "-f"; /* 5 */
+@@ -446,9 +451,14 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
+ src = mnt_fs_get_srcpath(cxt->fs);
+ target = mnt_fs_get_target(cxt->fs);
+
+- if (!src || !target)
++ if (!target)
+ return -EINVAL;
+-
++ if (!src) {
++ /* unnecessary, should be already resolved in
++ * mnt_context_prepare_srcpath(), but for sure... */
++ DBG(CXT, mnt_debug_h(cxt, "WARNING: source is NULL -- using \"none\"!"));
++ src = "none";
++ }
+ type = try_type ? : mnt_fs_get_fstype(cxt->fs);
+
+ if (!(flags & MS_MGC_MSK))
+diff --git a/libmount/src/fs.c b/libmount/src/fs.c
+index a28e66c..19650cb 100644
+--- a/libmount/src/fs.c
++++ b/libmount/src/fs.c
+@@ -304,11 +304,7 @@ int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
+
+ assert(fs);
+
+- if (source && !strcmp(source, "none")) {
+- free(source);
+- source = NULL;
+-
+- } else if (source && strchr(source, '=')) {
++ if (source && strchr(source, '=')) {
+ if (blkid_parse_tag_string(source, &t, &v) != 0)
+ return -1;
+ }
+@@ -341,6 +337,7 @@ int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
+
+ if (!fs)
+ return -EINVAL;
++
+ if (source) {
+ p = strdup(source);
+ if (!p)
+@@ -353,6 +350,41 @@ int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
+ return rc;
+ }
+
++/*
++ * Compares @fs source path with @path. The tailing slash is ignored.
++ * See also mnt_fs_match_source().
++ *
++ * Returns: 1 if @fs source path equal to @path, otherwise 0.
++ */
++int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
++{
++ const char *p;
++
++ if (!fs)
++ return 0;
++
++ p = mnt_fs_get_srcpath(fs);
++
++ if (!mnt_fs_is_pseudofs(fs))
++ return streq_except_trailing_slash(p, path);
++
++ if (!p && !path)
++ return 1;
++
++ return p && path && strcmp(p, path) == 0;
++}
++
++/*
++ * Compares @fs target path with @path. The tailing slash is ignored.
++ * See also mnt_fs_match_target().
++ *
++ * Returns: 1 if @fs target path equal to @path, otherwise 0.
++ */
++int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
++{
++ return fs && streq_except_trailing_slash(mnt_fs_get_target(fs), path);
++}
++
+ /**
+ * mnt_fs_get_tag:
+ * @fs: fs
+@@ -1114,7 +1146,7 @@ int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
+ return 0;
+
+ /* 1) native paths */
+- rc = !strcmp(target, fs->target);
++ rc = mnt_fs_streq_target(fs, target);
+
+ if (!rc && cache) {
+ /* 2) - canonicalized and non-canonicalized */
+@@ -1146,10 +1178,6 @@ int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
+ * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
+ * 2nd and 3rd attempts are not performed if @fs->source is tag.
+ *
+- * Note that valid source path is NULL; the libmount uses NULL instead of
+- * "none". The "none" is used in /proc/{mounts,self/mountninfo} for pseudo
+- * filesystems.
+- *
+ * Returns: 1 if @fs source is equal to @source else 0.
+ */
+ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
+@@ -1161,15 +1189,15 @@ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
+ if (!fs)
+ return 0;
+
+- /* undefined source -- "none" in /proc */
+- if (source == NULL && fs->source == NULL)
++ /* 1) native paths... */
++ if (mnt_fs_streq_srcpath(fs, source) == 1)
+ return 1;
+
+- if (source == NULL || fs->source == NULL)
++ if (!source || !fs->source)
+ return 0;
+
+- /* 1) native paths/tags */
+- if (streq_except_trailing_slash(source, fs->source))
++ /* ... and tags */
++ if (fs->tagname && strcmp(source, fs->source) == 0)
+ return 1;
+
+ if (!cache)
+@@ -1183,7 +1211,7 @@ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
+
+ /* 2) canonicalized and native */
+ src = mnt_fs_get_srcpath(fs);
+- if (src && streq_except_trailing_slash(cn, src))
++ if (src && mnt_fs_streq_srcpath(fs, cn))
+ return 1;
+
+ /* 3) canonicalized and canonicalized */
+diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
+index fa0edf5..a7b5c0d 100644
+--- a/libmount/src/mountP.h
++++ b/libmount/src/mountP.h
+@@ -367,6 +367,11 @@ extern struct libmnt_fs *mnt_copy_mtab_fs(const struct libmnt_fs *fs);
+ extern int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source);
+ extern int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype);
+
++/* exported in v2.22 */
++extern int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path);
++extern int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path);
++
++
+ /* context.c */
+ extern int mnt_context_prepare_srcpath(struct libmnt_context *cxt);
+ extern int mnt_context_prepare_target(struct libmnt_context *cxt);
+diff --git a/libmount/src/tab.c b/libmount/src/tab.c
+index 37f47bd..f3ec573 100644
+--- a/libmount/src/tab.c
++++ b/libmount/src/tab.c
+@@ -286,6 +286,11 @@ int mnt_table_next_child_fs(struct libmnt_table *tb, struct libmnt_iter *itr,
+
+ id = mnt_fs_get_id(fs);
+
++ /* avoid infinite loop. This only happens in rare cases
++ * such as in early userspace when the rootfs is its own parent */
++ if (id == parent_id)
++ continue;
++
+ if ((!lastchld_id || id > lastchld_id) &&
+ (!*chld || id < chld_id)) {
+ *chld = fs;
+@@ -438,7 +443,7 @@ struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *pat
+ /* native @target */
+ mnt_reset_iter(&itr, direction);
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- if (fs->target && strcmp(fs->target, path) == 0)
++ if (mnt_fs_streq_target(fs, path))
+ return fs;
+ }
+ if (!tb->cache || !(cn = mnt_resolve_path(path, tb->cache)))
+@@ -447,7 +452,7 @@ struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *pat
+ /* canonicalized paths in struct libmnt_table */
+ mnt_reset_iter(&itr, direction);
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- if (fs->target && strcmp(fs->target, cn) == 0)
++ if (mnt_fs_streq_target(fs, cn))
+ return fs;
+ }
+
+@@ -456,12 +461,13 @@ struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *pat
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+ char *p;
+
+- if (!fs->target || !mnt_fs_is_swaparea(fs) ||
++ if (!fs->target || mnt_fs_is_swaparea(fs) ||
+ (*fs->target == '/' && *(fs->target + 1) == '\0'))
+ continue;
+
+ p = mnt_resolve_path(fs->target, tb->cache);
+- if (strcmp(cn, p) == 0)
++ /* both canonicalized, strcmp() is fine here */
++ if (p && strcmp(cn, p) == 0)
+ return fs;
+ }
+ return NULL;
+@@ -480,9 +486,8 @@ struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *pat
+ * The 2nd, 3rd and 4th iterations are not performed when @tb cache is not
+ * set (see mnt_table_set_cache()).
+ *
+- * Note that valid source path is NULL; the libmount uses NULL instead of
+- * "none". The "none" is used in /proc/{mounts,self/mountninfo} for pseudo
+- * filesystems.
++ * Note that NULL is a valid source path; it will be replaced with "none". The
++ * "none" is used in /proc/{mounts,self/mountinfo} for pseudo filesystems.
+ *
+ * Returns: a tab entry or NULL.
+ */
+@@ -501,16 +506,10 @@ struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *pa
+ /* native paths */
+ mnt_reset_iter(&itr, direction);
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- const char *src = mnt_fs_get_source(fs);
+-
+- p = mnt_fs_get_srcpath(fs);
+-
+- if (path == NULL && src == NULL)
+- return fs; /* source is "none" */
+- if (path && p && streq_except_trailing_slash(p, path))
++ if (mnt_fs_streq_srcpath(fs, path))
+ return fs;
+- if (!p && src)
+- ntags++; /* mnt_fs_get_srcpath() returs nothing, it's TAG */
++ if (mnt_fs_get_tag(fs, NULL, NULL) == 0)
++ ntags++;
+ }
+
+ if (!path || !tb->cache || !(cn = mnt_resolve_path(path, tb->cache)))
+@@ -520,8 +519,7 @@ struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *pa
+ if (ntags < mnt_table_get_nents(tb)) {
+ mnt_reset_iter(&itr, direction);
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- p = mnt_fs_get_srcpath(fs);
+- if (p && streq_except_trailing_slash(p, cn))
++ if (mnt_fs_streq_srcpath(fs, cn))
+ return fs;
+ }
+ }
+@@ -552,7 +550,9 @@ struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *pa
+ if (mnt_fs_get_tag(fs, &t, &v))
+ continue;
+ x = mnt_resolve_tag(t, v, tb->cache);
+- if (x && streq_except_trailing_slash(x, cn))
++
++ /* both canonicalized, strcmp() is fine here */
++ if (x && strcmp(x, cn) == 0)
+ return fs;
+ }
+ }
+@@ -567,7 +567,9 @@ struct libmnt_fs *mnt_table_find_srcpath(struct libmnt_table *tb, const char *pa
+ p = mnt_fs_get_srcpath(fs);
+ if (p)
+ p = mnt_resolve_path(p, tb->cache);
+- if (p && streq_except_trailing_slash(cn, p))
++
++ /* both canonicalized, strcmp() is fine here */
++ if (p && strcmp(p, cn) == 0)
+ return fs;
+ }
+ }
+@@ -702,16 +704,18 @@ struct libmnt_fs *mnt_table_find_pair(struct libmnt_table *tb, const char *sourc
+ }
+
+ /*
+- * @tb: /proc/self/mountinfo
+- * @fs: filesystem
+- * @mountflags: MS_BIND or 0
+- * @fsroot: fs-root that will be probably used in the mountinfo file
++ * tb: /proc/self/mountinfo
++ * fs: filesystem
++ * mountflags: MS_BIND or 0
++ * fsroot: fs-root that will be probably used in the mountinfo file
+ * for @fs after mount(2)
+ *
+ * For btrfs subvolumes this function returns NULL, but @fsroot properly set.
+ *
+ * Returns: entry from @tb that will be used as a source for @fs if the @fs is
+ * bindmount.
++ *
++ * Don't export to library API!
+ */
+ struct libmnt_fs *mnt_table_get_fs_root(struct libmnt_table *tb,
+ struct libmnt_fs *fs,
+@@ -814,6 +818,20 @@ err:
+ return NULL;
+ }
+
++static int is_mountinfo(struct libmnt_table *tb)
++{
++ struct libmnt_fs *fs;
++
++ if (!tb)
++ return 0;
++
++ fs = list_first_entry(&tb->ents, struct libmnt_fs, ents);
++ if (fs && mnt_fs_is_kernel(fs) && mnt_fs_get_root(fs))
++ return 1;
++
++ return 0;
++}
++
+ /**
+ * mnt_table_is_mounted:
+ * @tb: /proc/self/mountinfo file
+@@ -829,10 +847,9 @@ err:
+ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
+ {
+ char *root = NULL;
+- struct libmnt_fs *src_fs;
+- const char *src, *tgt;
+- char *xsrc = NULL;
+- int flags = 0, rc = 0;
++ const char *src = NULL;
++ char *xsrc = NULL, *tgt;
++ int rc = 0;
+
+ assert(tb);
+ assert(fstab_fs);
+@@ -840,39 +857,49 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
+ if (mnt_fs_is_swaparea(fstab_fs))
+ return 0;
+
+- if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0)
+- flags = MS_BIND;
++ if (is_mountinfo(tb)) {
++ /* @tb is mountinfo, so we can try to use fs-roots */
++ struct libmnt_fs *fs;
++ int flags = 0;
++
++ if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0)
++ flags = MS_BIND;
+
+- src_fs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root);
+- if (src_fs)
+- src = mnt_fs_get_srcpath(src_fs);
++ fs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root);
++ if (fs)
++ src = mnt_fs_get_srcpath(fs);
++ }
++
++ if (src)
++ src = xsrc = mnt_resolve_spec(src, tb->cache);
+ else if (mnt_fs_is_pseudofs(fstab_fs))
+ src = mnt_fs_get_source(fstab_fs);
+ else
+ src = xsrc = mnt_resolve_spec(mnt_fs_get_source(fstab_fs),
+ tb->cache);
+
+- tgt = mnt_fs_get_target(fstab_fs);
++ tgt = mnt_resolve_path(mnt_fs_get_target(fstab_fs), tb->cache);
+
+- if (tgt && src && root) {
++ if (tgt && src) {
+ 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),
+- *r = mnt_fs_get_root(fs);
+-
+- /*
+- * Note that kernel can add tailing slash to the
+- * network filesystem source paths.
+- */
+- if (t && s && r &&
+- strcmp(t, tgt) == 0 &&
+- streq_except_trailing_slash(s, src) &&
+- strcmp(r, root) == 0)
++
++ if (root) {
++ /* mountinfo: compare root, source and target */
++ const char *r = mnt_fs_get_root(fs);
++
++ if (r && strcmp(r, root) == 0 &&
++ mnt_fs_streq_srcpath(fs, src) &&
++ mnt_fs_streq_target(fs, tgt))
++ break;
++ }
++ /* mtab: compare source and target */
++ else if (mnt_fs_streq_srcpath(fs, src) &&
++ mnt_fs_streq_target(fs, tgt))
+ break;
+ }
+ if (fs)
+@@ -881,6 +908,8 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
+
+ if (xsrc && !tb->cache)
+ free(xsrc);
++ if (!tb->cache)
++ free(tgt);
+
+ free(root);
+ return rc;
+diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
+index 0f618bb..28c8536 100644
+--- a/libmount/src/tab_parse.c
++++ b/libmount/src/tab_parse.c
+@@ -180,12 +180,7 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, char *s)
+ unmangle_string(fs->vfs_optstr);
+ unmangle_string(fstype);
+ unmangle_string(src);
+-
+- if (!strcmp(fs->fs_optstr, "none")) {
+- free(fs->fs_optstr);
+- fs->fs_optstr = NULL;
+- } else
+- unmangle_string(fs->fs_optstr);
++ unmangle_string(fs->fs_optstr);
+
+ rc = __mnt_fs_set_fstype_ptr(fs, fstype);
+ if (!rc) {
+@@ -733,21 +728,14 @@ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct
+ mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+
+ while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+- const char *s = mnt_fs_get_srcpath(fs),
+- *t = mnt_fs_get_target(fs),
+- *r = mnt_fs_get_root(fs);
++ const char *r = mnt_fs_get_root(fs);
+
+ if (fs->flags & MNT_FS_MERGED)
+ continue;
+
+- /*
+- * Note that kernel can add tailing slash to the network
+- * filesystem source path
+- */
+- if (s && t && r &&
+- strcmp(t, target) == 0 &&
+- streq_except_trailing_slash(s, src) &&
+- strcmp(r, root) == 0)
++ if (r && strcmp(r, root) == 0
++ && mnt_fs_streq_target(fs, target)
++ && mnt_fs_streq_srcpath(fs, src))
+ break;
+ }
+
+diff --git a/libmount/src/utils.c b/libmount/src/utils.c
+index c7a1fd1..4d316d1 100644
+--- a/libmount/src/utils.c
++++ b/libmount/src/utils.c
+@@ -235,6 +235,7 @@ int mnt_fstype_is_pseudofs(const char *type)
+ strcmp(type, "binfmt_misc") == 0 ||
+ strcmp(type, "fuse.gvfs-fuse-daemon") == 0 ||
+ strcmp(type, "debugfs") == 0 ||
++ strcmp(type, "nfsd") == 0 ||
+ strcmp(type, "spufs") == 0)
+ return 1;
+ return 0;
+diff --git a/login-utils/login.c b/login-utils/login.c
+index 84d8b1b..4f448f8 100644
+--- a/login-utils/login.c
++++ b/login-utils/login.c
+@@ -128,6 +128,22 @@ static int timeout = LOGIN_TIMEOUT;
+ static int child_pid = 0;
+ static volatile int got_sig = 0;
+
++#ifdef LOGIN_CHOWN_VCS
++/* true if the filedescriptor fd is a console tty, very Linux specific */
++static int is_consoletty(int fd)
++{
++ struct stat stb;
++
++ if ((fstat(fd, &stb) >= 0)
++ && (major(stb.st_rdev) == TTY_MAJOR)
++ && (minor(stb.st_rdev) < 64)) {
++ return 1;
++ }
++ return 0;
++}
++#endif
++
++
+ /*
+ * Robert Ambrose writes:
+ * A couple of my users have a problem with login processes hanging around
+@@ -316,15 +332,15 @@ static void chown_tty(struct login_context *cxt)
+
+ #ifdef LOGIN_CHOWN_VCS
+ if (is_consoletty(0)) {
+- if (chown(cxt->vcs, uid, gid)) /* vcs */
+- chown_err(cxt->vcs, uid, gid);
+- if (chmod(cxt->vcs, cxt->tty_mode))
+- chmod_err(cxt->vcs, cxt->tty_mode);
+-
+- if (chown(cxt->vcsa, uid, gid)) /* vcsa */
+- chown_err(cxt->vcsa, uid, gid);
+- if (chmod(cxt->vcsa, cxt->tty_mode))
+- chmod_err(cxt->vcsa, cxt->tty_mode);
++ if (chown(cxt->vcsn, uid, gid)) /* vcs */
++ chown_err(cxt->vcsn, uid, gid);
++ if (chmod(cxt->vcsn, cxt->tty_mode))
++ chmod_err(cxt->vcsn, cxt->tty_mode);
++
++ if (chown(cxt->vcsan, uid, gid)) /* vcsa */
++ chown_err(cxt->vcsan, uid, gid);
++ if (chmod(cxt->vcsan, cxt->tty_mode))
++ chmod_err(cxt->vcsan, cxt->tty_mode);
+ }
+ #endif
+ }
+@@ -403,21 +419,6 @@ static void init_tty(struct login_context *cxt)
+ }
+
+
+-#ifdef LOGIN_CHOWN_VCS
+-/* true if the filedescriptor fd is a console tty, very Linux specific */
+-static int is_consoletty(int fd)
+-{
+- struct stat stb;
+-
+- if ((fstat(fd, &stb) >= 0)
+- && (major(stb.st_rdev) == TTY_MAJOR)
+- && (minor(stb.st_rdev) < 64)) {
+- return 1;
+- }
+- return 0;
+-}
+-#endif
+-
+ /*
+ * Log failed login attempts in _PATH_BTMP if that exists.
+ * Must be called only with username the name of an actual user.
+@@ -1145,13 +1146,10 @@ static void init_environ(struct login_context *cxt)
+ setenv("TERM", termenv, 1);
+
+ if (pwd->pw_uid)
+- setenv("PATH", getlogindefs_str("ENV_PATH", _PATH_DEFPATH), 1);
+- else {
+- const char *x = getlogindefs_str("ENV_ROOTPATH", NULL);
+- if (!x)
+- x = getlogindefs_str("ENV_SUPATH", _PATH_DEFPATH_ROOT);
+- setenv("PATH", x, 1);
+- }
++ logindefs_setenv("PATH", "ENV_PATH", _PATH_DEFPATH);
++
++ else if (logindefs_setenv("PATH", "ENV_ROOTPATH", NULL) != 0)
++ logindefs_setenv("PATH", "ENV_SUPATH", _PATH_DEFPATH_ROOT);
+
+ /* mailx will give a funny error msg if you forget this one */
+ len = snprintf(tmp, sizeof(tmp), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+diff --git a/login-utils/logindefs.c b/login-utils/logindefs.c
+index fe590e9..e9517ac 100644
+--- a/login-utils/logindefs.c
++++ b/login-utils/logindefs.c
+@@ -211,6 +211,43 @@ const char *getlogindefs_str(const char *name, const char *dflt)
+ return ptr->value;
+ }
+
++/*
++ * For compatibililty with shadow-utils we have tu support additional
++ * syntax for environment variables in login.defs(5) file. The standard
++ * syntax is:
++ *
++ * ENV_FOO data
++ *
++ * but shadow-utils supports also
++ *
++ * ENV_FOO FOO=data
++ *
++ * the FOO= prefix has to be remove before we call setenv().
++ */
++int logindefs_setenv(const char *name, const char *conf, const char *dflt)
++{
++ const char *val = getlogindefs_str(conf, dflt);
++ const char *p;
++
++ if (!val)
++ return -1;
++
++ p = strchr(val, '=');
++ if (p) {
++ size_t sz = strlen(name);
++
++ if (strncmp(val, name, sz) == 0 && *(p + 1)) {
++ val = p + 1;
++ if (*val == '"')
++ val++;
++ if (!*val)
++ val = dflt;
++ }
++ }
++
++ return val ? setenv(name, val, 1) : -1;
++}
++
+ #ifdef TEST_PROGRAM
+ int main(int argc, char *argv[])
+ {
+diff --git a/login-utils/logindefs.h b/login-utils/logindefs.h
+index 37d19e1..163869d 100644
+--- a/login-utils/logindefs.h
++++ b/login-utils/logindefs.h
+@@ -5,5 +5,6 @@ extern int getlogindefs_bool(const char *name, int dflt);
+ extern long getlogindefs_num(const char *name, long dflt);
+ extern const char *getlogindefs_str(const char *name, const char *dflt);
+ extern void free_getlogindefs_data(void);
++extern int logindefs_setenv(const char *name, const char *conf, const char *dflt);
+
+ #endif /* UTIL_LINUX_LOGINDEFS_H */
+diff --git a/man/ru/Makefile.am b/man/ru/Makefile.am
+index 799feca..281ec23 100644
+--- a/man/ru/Makefile.am
++++ b/man/ru/Makefile.am
+@@ -1,9 +1,6 @@
+ include $(top_srcdir)/config/include-Makefile.am
+
+-mandir = @mandir@/ru
+-
+-dist_man_MANS =
+-
+ if BUILD_DDATE
+-dist_man_MANS += ddate.1
++ruman1_DATA = ddate.1
++EXTRA_DIST = $(ruman1_DATA)
+ endif
+diff --git a/misc-utils/lsblk.8 b/misc-utils/lsblk.8
+index 028b19f..286d54b 100644
+--- a/misc-utils/lsblk.8
++++ b/misc-utils/lsblk.8
+@@ -59,7 +59,7 @@ Use key="value" output format.
+ Use the raw output format.
+ .IP "\fB\-t, \-\-topology\fP"
+ Output info about block device topology.
+-This option is equivalent to "-o NAME,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED".
++This option is equivalent to "-o NAME,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE".
+ .SH NOTES
+ For the partitions are some information (e.g. queue attributes) inherited from
+ parental device.
+diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c
+index 8468b3f..54bf360 100644
+--- a/misc-utils/lsblk.c
++++ b/misc-utils/lsblk.c
+@@ -478,9 +478,14 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line
+ switch(id) {
+ case COL_NAME:
+ if (cxt->dm_name) {
+- snprintf(buf, sizeof(buf), "%s (%s)",
++ if ((lsblk->tt->flags & TT_FL_RAW) ||
++ (lsblk->tt->flags & TT_FL_EXPORT))
++ tt_line_set_data(ln, col, xstrdup(cxt->dm_name));
++ else {
++ snprintf(buf, sizeof(buf), "%s (%s)",
+ cxt->dm_name, cxt->name);
+- tt_line_set_data(ln, col, xstrdup(buf));
++ tt_line_set_data(ln, col, xstrdup(buf));
++ }
+ break;
+ }
+ case COL_KNAME:
+diff --git a/mount/fstab.5 b/mount/fstab.5
+index b0cd763..c618947 100644
+--- a/mount/fstab.5
++++ b/mount/fstab.5
+@@ -167,7 +167,7 @@ support filesystem
+ The subtype is defined by '.subtype' suffix. For
+ example 'fuse.sshfs'. It's recommended to use subtype notation rather than add
+ any prefix to the first fstab field (for example 'sshfs#example.com' is
+-depreacated).
++deprecated).
+ .RE
+
+ .B The fourth field
+diff --git a/sys-utils/losetup.8 b/sys-utils/losetup.8
+index a68836e..f50b072 100644
+--- a/sys-utils/losetup.8
++++ b/sys-utils/losetup.8
+@@ -80,6 +80,8 @@ for non-root users.
+ force loop driver to reread size of the file associated with the specified loop device
+ .IP "\fB\-d, \-\-detach\fP \fIloopdev\fP..."
+ detach the file or device associated with the specified loop device(s)
++.IP "\fB\-D, \-\-detach-all\fP"
++detach all associated loop devices
+ .IP "\fB\-e, \-E, \-\-encryption \fIencryption_type\fP"
+ enable data encryption with specified name or number
+ .IP "\fB\-f, \-\-find\fP"
+diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
+index 16ace6f..9f03151 100644
+--- a/sys-utils/losetup.c
++++ b/sys-utils/losetup.c
+@@ -362,7 +362,7 @@ int main(int argc, char **argv)
+ if (flags & LOOPDEV_FL_OFFSET)
+ loopcxt_set_offset(&lc, offset);
+ if (flags & LOOPDEV_FL_SIZELIMIT)
+- loopcxt_set_offset(&lc, sizelimit);
++ loopcxt_set_sizelimit(&lc, sizelimit);
+ if (lo_flags)
+ loopcxt_set_flags(&lc, lo_flags);
+ if ((res = loopcxt_set_backing_file(&lc, file))) {
+diff --git a/sys-utils/mount.8 b/sys-utils/mount.8
+index 78e7a41..44d4402 100644
+--- a/sys-utils/mount.8
++++ b/sys-utils/mount.8
+@@ -2760,6 +2760,10 @@ mount failure
+ .TP
+ .BR 64
+ some mount succeeded
++.RE
++
++The command mount -a returns 0 (all success), 32 (all failed) or 64 (some
++failed, some success).
+
+ .SH NOTES
+ The syntax of external mount helpers is:
+diff --git a/sys-utils/mount.c b/sys-utils/mount.c
+index 15510e0..12ec372 100644
+--- a/sys-utils/mount.c
++++ b/sys-utils/mount.c
+@@ -182,6 +182,8 @@ static int mount_all(struct libmnt_context *cxt)
+ struct libmnt_fs *fs;
+ int mntrc, ignored, rc = MOUNT_EX_SUCCESS;
+
++ int nsucc = 0, nerrs = 0;
++
+ itr = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!itr) {
+ warn(_("failed to initialize libmount iterator"));
+@@ -197,31 +199,40 @@ static int mount_all(struct libmnt_context *cxt)
+ printf(ignored == 1 ? _("%-25s: ignored\n") :
+ _("%-25s: already mounted\n"),
+ tgt);
+-
+ } else if (mnt_context_is_fork(cxt)) {
+ if (mnt_context_is_verbose(cxt))
+ printf("%-25s: mount successfully forked\n", tgt);
+ } else {
+- rc |= mk_exit_code(cxt, mntrc);
++ mk_exit_code(cxt, mntrc); /* to print warnings */
+
+ if (mnt_context_get_status(cxt)) {
+- rc |= MOUNT_EX_SOMEOK;
++ nsucc++;
+
+ if (mnt_context_is_verbose(cxt))
+ printf("%-25s: successfully mounted\n", tgt);
+- }
++ } else
++ nerrs++;
+ }
+ }
+
+ if (mnt_context_is_parent(cxt)) {
+ /* wait for mount --fork children */
+- int nerrs = 0, nchildren = 0;
++ int nchildren = 0;
++
++ nerrs = 0, nsucc = 0;
+
+ rc = mnt_context_wait_for_children(cxt, &nchildren, &nerrs);
+ if (!rc && nchildren)
+- rc = nchildren == nerrs ? MOUNT_EX_FAIL : MOUNT_EX_SOMEOK;
++ nsucc = nchildren - nerrs;
+ }
+
++ if (nerrs == 0)
++ rc = MOUNT_EX_SUCCESS; /* all success */
++ else if (nsucc == 0)
++ rc = MOUNT_EX_FAIL; /* all failed */
++ else
++ rc = MOUNT_EX_SOMEOK; /* some success, some failed */
++
+ mnt_free_iter(itr);
+ return rc;
+ }
+@@ -290,6 +301,25 @@ static void selinux_warning(struct libmnt_context *cxt, const char *tgt)
+ # define selinux_warning(_x, _y)
+ #endif
+
++/* temporary in mount(8) for v2.21.x releases, in v2.22 will be in libmount
++ */
++static int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
++{
++ const char *p;
++
++ if (!fs)
++ return 0;
++
++ p = mnt_fs_get_srcpath(fs);
++
++ if (!mnt_fs_is_pseudofs(fs))
++ return streq_except_trailing_slash(p, path);
++
++ if (!p && !path)
++ return 1;
++
++ return p && path && strcmp(p, path) == 0;
++}
+
+ /*
+ * rc = 0 success
+@@ -336,7 +366,11 @@ try_readonly:
+ return MOUNT_EX_USAGE;
+ }
+
+- if (src == NULL || tgt == NULL) {
++ /*
++ * TODO: add mnt_context_fstab_applied() to check if we found
++ * target/source in the file.
++ */
++ if (!tgt) {
+ if (mflags & MS_REMOUNT)
+ warnx(_("%s not mounted"), src ? src : tgt);
+ else
+@@ -408,7 +442,7 @@ try_readonly:
+ const char *s = mnt_fs_get_srcpath(fs),
+ *t = mnt_fs_get_target(fs);
+
+- if (t && s && streq_except_trailing_slash(s, src))
++ if (t && s && mnt_fs_streq_srcpath(fs, src))
+ fprintf(stderr, _(
+ " %s is already mounted on %s\n"), s, t);
+ }
+@@ -697,7 +731,7 @@ int main(int argc, char **argv)
+ longopts, NULL)) != -1) {
+
+ /* only few options are allowed for non-root users */
+- if (mnt_context_is_restricted(cxt) && !strchr("hlLUVvpr", c))
++ if (mnt_context_is_restricted(cxt) && !strchr("hlLUVvpri", c))
+ exit_non_root(option_to_longopt(c, longopts));
+
+ switch(c) {
+diff --git a/sys-utils/mountpoint.c b/sys-utils/mountpoint.c
+index 5cc833d..d0a0069 100644
+--- a/sys-utils/mountpoint.c
++++ b/sys-utils/mountpoint.c
+@@ -40,12 +40,12 @@
+
+ static int quiet;
+
+-static dev_t dir_to_device(const char *spec)
++static int dir_to_device(const char *spec, dev_t *dev)
+ {
+ struct libmnt_table *tb = mnt_new_table_from_file("/proc/self/mountinfo");
+ struct libmnt_fs *fs;
+ struct libmnt_cache *cache;
+- dev_t res = 0;
++ int rc = -1;
+
+ if (!tb) {
+ /*
+@@ -57,7 +57,7 @@ static dev_t dir_to_device(const char *spec)
+ int len;
+
+ if (stat(spec, &st) != 0)
+- return 0;
++ return -1;
+
+ cn = mnt_resolve_path(spec, NULL); /* canonicalize */
+
+@@ -65,15 +65,17 @@ static dev_t dir_to_device(const char *spec)
+ free(cn);
+
+ if (len < 0 || (size_t) len + 1 > sizeof(buf))
+- return 0;
++ return -1;
+ if (stat(buf, &pst) !=0)
+- return 0;
++ return -1;
+
+ if ((st.st_dev != pst.st_dev) ||
+- (st.st_dev == pst.st_dev && st.st_ino == pst.st_ino))
+- return st.st_dev;
++ (st.st_dev == pst.st_dev && st.st_ino == pst.st_ino)) {
++ *dev = st.st_dev;
++ return 0;
++ }
+
+- return 0;
++ return -1;
+ }
+
+ /* to canonicalize all necessary paths */
+@@ -81,12 +83,14 @@ static dev_t dir_to_device(const char *spec)
+ mnt_table_set_cache(tb, cache);
+
+ fs = mnt_table_find_target(tb, spec, MNT_ITER_BACKWARD);
+- if (fs && mnt_fs_get_target(fs))
+- res = mnt_fs_get_devno(fs);
++ if (fs && mnt_fs_get_target(fs)) {
++ *dev = mnt_fs_get_devno(fs);
++ rc = 0;
++ }
+
+ mnt_free_table(tb);
+ mnt_free_cache(cache);
+- return res;
++ return rc;
+ }
+
+ static int print_devno(const char *devname, struct stat *st)
+@@ -185,8 +189,8 @@ int main(int argc, char **argv)
+ errx(EXIT_FAILURE, _("%s: not a directory"), spec);
+ return EXIT_FAILURE;
+ }
+- src = dir_to_device(spec);
+- if (!src) {
++
++ if ( dir_to_device(spec, &src)) {
+ if (!quiet)
+ printf(_("%s is not a mountpoint\n"), spec);
+ return EXIT_FAILURE;
+diff --git a/term-utils/script.c b/term-utils/script.c
+index 58f9790..0d891b8 100644
+--- a/term-utils/script.c
++++ b/term-utils/script.c
+@@ -437,6 +437,16 @@ doshell(void) {
+ else
+ shname = shell;
+
++ /*
++ * When invoked from within /etc/csh.login, script spawns a csh shell
++ * that spawns programs that cannot be killed with a SIGTERM. This is
++ * because csh has a documented behaviour wherein it disables all
++ * signals when processing the /etc/csh.* files.
++ *
++ * Let's restore the default behavior.
++ */
++ signal(SIGTERM, SIG_DFL);
++
+ if (cflg)
+ execl(shell, shname, "-c", cflg, NULL);
+ else
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index fd62519..2c72318 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -7,5 +7,5 @@ EXTRA_DIST = expected \
+ functions.sh \
+ run.sh
+
+-distclean-local:
++clean-local:
+ rm -rf output diff
+diff --git a/tests/expected/libmount/tabfiles-find-target2 b/tests/expected/libmount/tabfiles-find-target2
+new file mode 100644
+index 0000000..8a6c57b
+--- /dev/null
++++ b/tests/expected/libmount/tabfiles-find-target2
+@@ -0,0 +1,5 @@
++------ fs:
++source: /dev/foo
++target: /any/foo/
++fstype: auto
++optstr: defaults
+diff --git a/tests/expected/libmount/tabfiles-find-target3 b/tests/expected/libmount/tabfiles-find-target3
+new file mode 100644
+index 0000000..8a6c57b
+--- /dev/null
++++ b/tests/expected/libmount/tabfiles-find-target3
+@@ -0,0 +1,5 @@
++------ fs:
++source: /dev/foo
++target: /any/foo/
++fstype: auto
++optstr: defaults
+diff --git a/tests/expected/libmount/tabfiles-parse-fstab b/tests/expected/libmount/tabfiles-parse-fstab
+index 14bdfb4..d661526 100644
+--- a/tests/expected/libmount/tabfiles-parse-fstab
++++ b/tests/expected/libmount/tabfiles-parse-fstab
+@@ -58,3 +58,8 @@ target: /mnt/gogogo
+ fstype: cifs
+ optstr: user=SRGROUP/baby,noauto
+ user-optstr: user=SRGROUP/baby,noauto
++------ fs:
++source: /dev/foo
++target: /any/foo/
++fstype: auto
++optstr: defaults
+diff --git a/tests/expected/libmount/tabfiles-parse-mountinfo b/tests/expected/libmount/tabfiles-parse-mountinfo
+index 95182dd..4470801 100644
+--- a/tests/expected/libmount/tabfiles-parse-mountinfo
++++ b/tests/expected/libmount/tabfiles-parse-mountinfo
+@@ -296,7 +296,7 @@ id: 41
+ parent: 20
+ devno: 253:0
+ ------ fs:
+-source: (null)
++source: none
+ target: /proc/sys/fs/binfmt_misc
+ fstype: binfmt_misc
+ optstr: rw,relatime
+diff --git a/tests/expected/libmount/tabfiles-parse-mtab b/tests/expected/libmount/tabfiles-parse-mtab
+index d7171ea..ffd0c13 100644
+--- a/tests/expected/libmount/tabfiles-parse-mtab
++++ b/tests/expected/libmount/tabfiles-parse-mtab
+@@ -42,7 +42,7 @@ fstype: ext4
+ optstr: rw,noatime
+ VFS-optstr: rw,noatime
+ ------ fs:
+-source: (null)
++source: none
+ target: /proc/sys/fs/binfmt_misc
+ fstype: binfmt_misc
+ optstr: rw
+diff --git a/tests/expected/libmount/update-utab-mount b/tests/expected/libmount/update-utab-mount
+index 1784e00..58a0179 100644
+--- a/tests/expected/libmount/update-utab-mount
++++ b/tests/expected/libmount/update-utab-mount
+@@ -1,3 +1,3 @@
+ SRC=/dev/sdb1 TARGET=/mnt/bar ROOT=/ OPTS=user
+ SRC=/dev/sda2 TARGET=/mnt/xyz ROOT=/ OPTS=loop=/dev/loop0,uhelper=hal
+-TARGET=/proc ROOT=/ OPTS=user
++SRC=none TARGET=/proc ROOT=/ OPTS=user
+diff --git a/tests/expected/libmount/update-utab-move b/tests/expected/libmount/update-utab-move
+index 12917cc..6008140 100644
+--- a/tests/expected/libmount/update-utab-move
++++ b/tests/expected/libmount/update-utab-move
+@@ -1,3 +1,3 @@
+ SRC=/dev/sdb1 TARGET=/mnt/newbar ROOT=/ OPTS=user
+ SRC=/dev/sda2 TARGET=/mnt/newxyz ROOT=/ OPTS=loop=/dev/loop0,uhelper=hal
+-TARGET=/proc ROOT=/ OPTS=user
++SRC=none TARGET=/proc ROOT=/ OPTS=user
+diff --git a/tests/expected/libmount/update-utab-remount b/tests/expected/libmount/update-utab-remount
+index 737e2a3..8e344b3 100644
+--- a/tests/expected/libmount/update-utab-remount
++++ b/tests/expected/libmount/update-utab-remount
+@@ -1,3 +1,3 @@
+ SRC=/dev/sdb1 TARGET=/mnt/newbar ROOT=/ OPTS=user
+ SRC=/dev/sda2 TARGET=/mnt/newxyz ROOT=/ OPTS=user
+-TARGET=/proc ROOT=/ OPTS=user
++SRC=none TARGET=/proc ROOT=/ OPTS=user
+diff --git a/tests/expected/mount/fstab-none b/tests/expected/mount/fstab-none
+new file mode 100644
+index 0000000..3582111
+--- /dev/null
++++ b/tests/expected/mount/fstab-none
+@@ -0,0 +1 @@
++Success
+diff --git a/tests/expected/mount/shared-subtree b/tests/expected/mount/shared-subtree
+new file mode 100644
+index 0000000..3582111
+--- /dev/null
++++ b/tests/expected/mount/shared-subtree
+@@ -0,0 +1 @@
++Success
+diff --git a/tests/expected/mount/shared-subtree-make-private b/tests/expected/mount/shared-subtree-make-private
+new file mode 100644
+index 0000000..39cdd0d
+--- /dev/null
++++ b/tests/expected/mount/shared-subtree-make-private
+@@ -0,0 +1 @@
++-
+diff --git a/tests/expected/mount/shared-subtree-make-shared b/tests/expected/mount/shared-subtree-make-shared
+new file mode 100644
+index 0000000..8a205e8
+--- /dev/null
++++ b/tests/expected/mount/shared-subtree-make-shared
+@@ -0,0 +1 @@
++shared
+diff --git a/tests/expected/mount/shared-subtree-make-unbindable b/tests/expected/mount/shared-subtree-make-unbindable
+new file mode 100644
+index 0000000..376cfac
+--- /dev/null
++++ b/tests/expected/mount/shared-subtree-make-unbindable
+@@ -0,0 +1 @@
++unbindable
+diff --git a/tests/functions.sh b/tests/functions.sh
+index 85b1621..6556e4e 100644
+--- a/tests/functions.sh
++++ b/tests/functions.sh
+@@ -93,6 +93,8 @@ function ts_init_core_subtest_env {
+ TS_MOUNTPOINT="$TS_OUTDIR/${TS_TESTNAME}-${TS_SUBNAME}-mnt"
+
+ rm -f $TS_OUTPUT $TS_VGDUMP
++ [ -d "$TS_OUTDIR" ] || mkdir -p "$TS_OUTDIR"
++
+ touch $TS_OUTPUT
+ [ -n "$TS_VALGRIND_CMD" ] && touch $TS_VGDUMP
+ }
+@@ -127,8 +129,6 @@ function ts_init_env {
+
+ BLKID_FILE="$TS_OUTDIR/${TS_TESTNAME}.blkidtab"
+
+- [ -d "$TS_OUTDIR" ] || mkdir -p "$TS_OUTDIR"
+- [ -d "$TS_DIFFDIR" ] || mkdir -p "$TS_DIFFDIR"
+
+ declare -a TS_SUID_PROGS
+ declare -a TS_SUID_USER
+@@ -141,6 +141,8 @@ function ts_init_env {
+ export BLKID_FILE
+
+ rm -f $TS_OUTPUT $TS_VGDUMP
++ [ -d "$TS_OUTDIR" ] || mkdir -p "$TS_OUTDIR"
++
+ touch $TS_OUTPUT
+ [ -n "$TS_VALGRIND_CMD" ] && touch $TS_VGDUMP
+
+@@ -219,8 +221,15 @@ function ts_gen_diff {
+ local res=0
+
+ if [ -s "$TS_OUTPUT" ]; then
++
++ [ -d "$TS_DIFFDIR" ] || mkdir -p "$TS_DIFFDIR"
+ diff -u $TS_EXPECTED $TS_OUTPUT > $TS_DIFF
+- [ -s $TS_DIFF ] && res=1
++
++ if [ -s $TS_DIFF ]; then
++ res=1
++ else
++ rm -f $TS_DIFF;
++ fi
+ else
+ res=1
+ fi
+diff --git a/tests/ts/build-sys/config b/tests/ts/build-sys/config
+index 7ede38c..e2c2b00 100755
+--- a/tests/ts/build-sys/config
++++ b/tests/ts/build-sys/config
+@@ -52,9 +52,18 @@ for conf in $config_gen_dir/config-gen.d/*.conf; do
+ esac
+ fi
+ done
++
++ # clean the tree, but exclude tests/{diff,output} dirs
++ #
++ [ -d tests/diff ] && mv tests/diff tests/diff.save
++ [ -d tests/output ] && mv tests/output tests/output.save
++
+ make -j clean &> /dev/null
+- cd $olddir
+
++ [ -d tests/diff.save ] && mv tests/diff.save tests/diff
++ [ -d tests/output.save ] && mv tests/output.save tests/output
++
++ cd $olddir
+ ts_finalize_subtest
+ done
+
+diff --git a/tests/ts/libmount/context-utab b/tests/ts/libmount/context-utab
+index aa49806..4c1d117 100755
+--- a/tests/ts/libmount/context-utab
++++ b/tests/ts/libmount/context-utab
+@@ -67,6 +67,8 @@ grep -q $DEVICE /proc/mounts || \
+ echo "(by device) cannot find $DEVICE in /proc/mounts" >> $TS_OUTPUT 2>&1
+ ts_finalize_subtest
+
++sleep 1
++
+ ts_init_subtest "umount-by-devname"
+ ts_valgrind $TESTPROG --umount $DEVICE >> $TS_OUTPUT 2>&1
+ grep -q $DEVICE /proc/mounts &&
+@@ -81,6 +83,8 @@ grep -q $DEVICE $LIBMOUNT_UTAB || \
+ echo "(by label) cannot find $DEVICE in $LIBMOUNT_UTAB" >> $TS_OUTPUT 2>&1
+ ts_finalize_subtest
+
++sleep 1
++
+ ts_init_subtest "umount"
+ ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
+ grep -q $DEVICE $LIBMOUNT_UTAB && \
+@@ -94,6 +98,8 @@ if [ -x "/sbin/mkfs.btrfs" ]; then
+ /sbin/btrfsctl -S sub $MOUNTPOINT &> /dev/null
+ umount $MOUNTPOINT &> /dev/null
+
++ sleep 1
++
+ ts_init_subtest "mount-uhelper-subvol"
+ mkdir -p $MOUNTPOINT &> /dev/null
+ ts_valgrind $TESTPROG --mount -o uhelper=foo,rw,subvol=sub $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>&1
+@@ -105,6 +111,8 @@ if [ -x "/sbin/mkfs.btrfs" ]; then
+ $TS_CMD_FINDMNT --mtab $MOUNTPOINT -o OPTIONS -n >> $TS_OUTPUT 2>&1
+ ts_log "---"
+
++ sleep 1
++
+ ts_init_subtest "umount-subvol"
+ ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
+ grep -q $DEVICE $LIBMOUNT_UTAB && \
+diff --git a/tests/ts/libmount/files/fstab b/tests/ts/libmount/files/fstab
+index 2503065..a8f73bc 100644
+--- a/tests/ts/libmount/files/fstab
++++ b/tests/ts/libmount/files/fstab
+@@ -10,3 +10,5 @@ proc /proc proc defaults 0 0
+
+ foo.com:/mnt/share /mnt/remote nfs noauto
+ //bar.com/gogogo /mnt/gogogo cifs user=SRGROUP/baby,noauto
++
++/dev/foo /any/foo/ auto defaults 0 0
+diff --git a/tests/ts/libmount/tabfiles b/tests/ts/libmount/tabfiles
+index 7f4913e..671c649 100755
+--- a/tests/ts/libmount/tabfiles
++++ b/tests/ts/libmount/tabfiles
+@@ -47,6 +47,16 @@ ts_valgrind $TESTPROG --find-forward "$TS_SELF/files/fstab" target /home/foo &>
+ sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT
+ ts_finalize_subtest
+
++ts_init_subtest "find-target2"
++ts_valgrind $TESTPROG --find-forward "$TS_SELF/files/fstab" target /any/foo &> $TS_OUTPUT
++sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT
++ts_finalize_subtest
++
++ts_init_subtest "find-target3"
++ts_valgrind $TESTPROG --find-forward "$TS_SELF/files/fstab" target /any/foo/ &> $TS_OUTPUT
++sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT
++ts_finalize_subtest
++
+ ts_init_subtest "find-pair"
+ ts_valgrind $TESTPROG --find-pair "$TS_SELF/files/mtab" /dev/mapper/kzak-home /home/kzak &> $TS_OUTPUT
+ sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT
+diff --git a/tests/ts/mount/fstab-none b/tests/ts/mount/fstab-none
+new file mode 100755
+index 0000000..62a89ca
+--- /dev/null
++++ b/tests/ts/mount/fstab-none
+@@ -0,0 +1,30 @@
++#!/bin/bash
++
++TS_TOPDIR="$(dirname $0)/../.."
++TS_DESC="none"
++
++. $TS_TOPDIR/functions.sh
++ts_init "$*"
++ts_skip_nonroot
++
++set -o pipefail
++
++ts_fstab_add "none" "$TS_MOUNTPOINT" "tmpfs" "rw,nosuid,nodev,relatime"
++
++mkdir -p $TS_MOUNTPOINT
++
++$TS_CMD_MOUNT $TS_MOUNTPOINT 2>&1 >> $TS_OUTPUT
++
++$TS_CMD_FINDMNT --target "$TS_MOUNTPOINT" &> /dev/null
++[ $? -eq 0 ] || ts_die "Not found target (mount failed?)"
++
++$TS_CMD_FINDMNT --source "none" --target "$TS_MOUNTPOINT" &> /dev/null
++[ $? -eq 0 ] || ts_die "Not found source and target"
++
++$TS_CMD_UMOUNT $TS_MOUNTPOINT || ts_die "Cannot umount $TS_MOUNTPOINT"
++
++ts_fstab_clean
++
++ts_log "Success"
++ts_finalize
++
+diff --git a/tests/ts/mount/shared-subtree b/tests/ts/mount/shared-subtree
+new file mode 100755
+index 0000000..a0a76c5
+--- /dev/null
++++ b/tests/ts/mount/shared-subtree
+@@ -0,0 +1,58 @@
++#!/bin/bash
++
++TS_TOPDIR="$(dirname $0)/../.."
++TS_DESC="shared-subtree"
++
++. $TS_TOPDIR/functions.sh
++ts_init "$*"
++ts_skip_nonroot
++
++function get_attr()
++{
++ # It's usually stupid idea to use 'grep | awk',
++ # but use paths in awk /regex/ is too tricky...
++ #
++ # TODO; improve libmount and findmnt to return the
++ # shared-subtree flags
++ #
++ echo $(grep "$1" /proc/self/mountinfo | \
++ awk '{print $7}' | \
++ awk -F ':' '{ print $1 }')
++}
++
++[ -d $TS_MOUNTPOINT ] || mkdir -p $TS_MOUNTPOINT
++
++# bind
++$TS_CMD_MOUNT --bind $TS_MOUNTPOINT $TS_MOUNTPOINT
++
++# check the bind
++$TS_CMD_FINDMNT --kernel --target $TS_MOUNTPOINT &> /dev/null
++[ "$?" == "0" ] || ts_die "Cannot find binded $TS_MOUNTPOINT in /proc/self/mountinfo"
++
++# use the same mounpoint for all sub-tests
++MOUNTPOINT="$TS_MOUNTPOINT"
++
++
++ts_init_subtest "make-shared"
++$TS_CMD_MOUNT --make-shared $MOUNTPOINT >> $TS_OUTPUT 2>&1
++echo "$(get_attr $MOUNTPOINT)" >> $TS_OUTPUT
++ts_finalize_subtest
++
++ts_init_subtest "make-private"
++$TS_CMD_MOUNT --make-private $MOUNTPOINT >> $TS_OUTPUT 2>&1
++echo "$(get_attr $MOUNTPOINT)" >> $TS_OUTPUT
++ts_finalize_subtest
++
++ts_init_subtest "make-unbindable"
++$TS_CMD_MOUNT --make-unbindable $MOUNTPOINT >> $TS_OUTPUT 2>&1
++echo "$(get_attr $MOUNTPOINT)" >> $TS_OUTPUT
++ts_finalize_subtest
++
++
++# clean up
++$TS_CMD_UMOUNT $TS_MOUNTPOINT
++rmdir $TS_MOUNTPOINT
++
++ts_log "Success"
++ts_finalize
++