[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: failure of pwd-long test on linux bind mount
From: |
Jim Meyering |
Subject: |
Re: failure of pwd-long test on linux bind mount |
Date: |
Sat, 20 Jan 2007 22:01:32 +0100 |
Michael Stone <address@hidden> wrote:
> If you run the coreutils pwd-long test from within a bind mount it'll
> fail. Reproduce with:
> | mkdir test1 test2
> | mount --bind test1 test2
> | cd test2
> | env BUILD_SRC_DIR=/bin ./pwd-long
>
> looking at what pwd returns:
> (expects)
> /tmp/test2/pwd-long.tmp/19496/zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz/zzzzz[...]
> (gets)
> /tmp/test1/pwd-long.tmp/19496/zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz/zzzzz[...]
>
> this actually makes sense based on the algorithm (stat ., list .., find
> the directory which has the right inode) and I'm not sure that I can
> think of a way to rewrite the test so that it would actually work on a
> bind mount. Maybe we could only compare the part from pwd-long.tmp on,
> but would that still test for whatever failure lead to the test in the
> first place?
Thanks.
I've fixed it on the trunk like this:
2007-01-20 Jim Meyering <address@hidden>
* tests/misc/pwd-long: Work properly even when run from the
wrong one of two or more bind-mounted sibling directories.
Suggestion from Mike Stone in <http://bugs.debian.org/380552>.
diff --git a/tests/misc/pwd-long b/tests/misc/pwd-long
index 546550e..1306b32 100755
--- a/tests/misc/pwd-long
+++ b/tests/misc/pwd-long
@@ -1,7 +1,7 @@
#!/bin/sh
# Ensure that pwd works even when run from a very deep directory.
-# Copyright (C) 2006 Free Software Foundation, Inc.
+# Copyright (C) 2006-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -51,18 +51,39 @@ $PERL -Tw -- - <<\EOF
# Show that pwd works even when the length of the resulting
# directory name is longer than PATH_MAX.
use strict;
-use Cwd;
(my $ME = $ENV{ARGV_0}) =~ s|.*/||;
+sub normalize_to_cwd_relative ($$$)
+{
+ my ($dir, $dev, $ino) = @_;
+ my $slash = -1;
+ my $next_slash;
+ while (1)
+ {
+ $slash = index $dir, '/', $slash + 1;
+ $slash <= -1
+ and die "$ME: $dir does not contain old CWD\n";
+ my $dir_prefix = $slash ? substr ($dir, 0, $slash) : '/';
+ my ($d, $i) = (stat $dir_prefix)[0, 1];
+ $d == $dev && $i == $ino
+ and return substr $dir, $slash + 1;
+ }
+}
+
# Set up a safe, well-known environment
delete @ENV{qw(BASH_ENV CDPATH ENV PATH)};
$ENV{IFS} = '';
-my $cwd = $ENV{CWD};
+# Save CWD's device and inode numbers.
+my ($dev, $ino) = (stat '.')[0, 1];
+
+# Construct the expected "."-relative part of pwd's output.
my $z = 'z' x 31;
my $n = 256;
-my $expected = $cwd . ("/$z" x $n);
+my $expected = "/$z" x $n;
+# Remove the leading "/".
+substr ($expected, 0, 1) = '';
my $i = 0;
do
@@ -89,6 +110,15 @@ my $pwd_binary = "$build_src_dir/pwd";
-x $pwd_binary
or die "$ME: $pwd_binary is not an executable file\n";
chomp (my $actual = `$pwd_binary`);
+
+# Convert the absolute name from pwd into a $CWD-relative name.
+# This is necessary in order to avoid a spurious failure when run
+# from a directory in a bind-mounted partition. What happens is
+# pwd reads a ".." that contains two or more entries with identical
+# dev,ino that match the ones we're looking for, and it chooses a
+# name that does not correspond to the one already recorded in $CWD.
+$actual = normalize_to_cwd_relative $actual, $dev, $ino;
+
if ($expected ne $actual)
{
my $e_len = length $expected;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: failure of pwd-long test on linux bind mount,
Jim Meyering <=