diff options
author | root <root@rshg054.dnsready.net> | 2012-03-16 00:01:21 +0000 |
---|---|---|
committer | root <root@rshg054.dnsready.net> | 2012-03-16 00:01:21 +0000 |
commit | cd326e60e1e54ebe83bd700850b313c69f419eef (patch) | |
tree | b15df594ae07c150fff4a55c0d1a01885b232dd0 /core/util-linux | |
parent | 14635ca5380a480450a66c3fcc29992d29a2bd8e (diff) |
Fri Mar 16 00:01:21 UTC 2012
Diffstat (limited to 'core/util-linux')
-rw-r--r-- | core/util-linux/PKGBUILD | 47 | ||||
-rw-r--r-- | core/util-linux/stable-fixes-2.21.patch | 1516 |
2 files changed, 1540 insertions, 23 deletions
diff --git a/core/util-linux/PKGBUILD b/core/util-linux/PKGBUILD index 26faab001..d0d499374 100644 --- a/core/util-linux/PKGBUILD +++ b/core/util-linux/PKGBUILD @@ -1,23 +1,21 @@ -# $Id: PKGBUILD 146393 2012-01-10 11:39:59Z tomegun $ +# $Id: PKGBUILD 153482 2012-03-14 23:26:17Z tomegun $ # Maintainer: Tom Gundersen <teg@jklm.no> # Contributor: judd <jvinet@zeroflux.org> pkgname=util-linux -pkgver=2.20.1 -pkgrel=2 +pkgver=2.21 +pkgrel=5 pkgdesc="Miscellaneous system utilities for Linux" -url="http://userweb.kernel.org/~kzak/util-linux-ng/" +url="http://www.kernel.org/pub/linux/utils/util-linux/" arch=('i686' 'x86_64') groups=('base') -depends=('filesystem') -replaces=('linux32' 'util-linux-ng') -conflicts=('linux32' 'util-linux-ng' 'e2fsprogs<1.41.8-2') -provides=('linux32' "util-linux-ng=${pkgver}") +depends=('udev') +conflicts=('util-linux-ng') +provides=("util-linux-ng=${pkgver}") license=('GPL2') options=('!libtool') -#source=(ftp://ftp.kernel.org/pub/linux/utils/${pkgname}/v${pkgver}/${pkgname}-${pkgver}.tar.bz2) -source=(ftp://ftp.infradead.org/pub/${pkgname}/v2.20/${pkgname}-${pkgver}.tar.bz2 - 0001-findmnt-support-alternative-location-of-fstab.patch) +source=(ftp://ftp.kernel.org/pub/linux/utils/${pkgname}/v${pkgver}/${pkgname}-${pkgver}.tar.xz + stable-fixes-2.21.patch) optdepends=('perl: for chkdupexe support') build() { @@ -26,15 +24,13 @@ build() { # hardware clock sed -e 's%etc/adjtime%var/lib/hwclock/adjtime%' -i include/pathnames.h - # backport patch needed for usr support in initramfs - patch -p1 -i ../0001-findmnt-support-alternative-location-of-fstab.patch + patch -p1 -i ../stable-fixes-2.21.patch - ./configure --enable-arch\ - --enable-write\ - --enable-raw\ - --disable-wall\ - --enable-partx\ - --enable-libmount-mount + ./configure --prefix=/usr \ + --libdir=/usr/lib \ + --enable-write \ + --enable-raw \ + --disable-wall make } @@ -42,9 +38,14 @@ build() { package() { cd "${srcdir}/${pkgname}-${pkgver}" - install -dm755 "${pkgdir}/var/lib/hwclock" - make DESTDIR="${pkgdir}" install + + cd "${pkgdir}" + + install -dm755 var/lib/hwclock + + # delete stray empty dir, fixed upstream + rm -r usr/share/man/ru } -md5sums=('079b37517fd4e002a2e6e992e8b4e361' - '823e2d87885b81f245b8c368e28f8cab') +md5sums=('208aa058f4117759d2939d1be7d662fc' + '415b850a4efa9174cd9c34022949f177') diff --git a/core/util-linux/stable-fixes-2.21.patch b/core/util-linux/stable-fixes-2.21.patch new file mode 100644 index 000000000..3c6c32483 --- /dev/null +++ b/core/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 ++ |