bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

getcwd: Fix test failure when building on a Linux 9p file system


From: Bruno Haible
Subject: getcwd: Fix test failure when building on a Linux 9p file system
Date: Sun, 13 Jan 2019 19:22:43 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; )

I'm testing a POSIX testdir of gnulib on a 9p file system [1], which
serves as a shared directory between the host and the guest VM. 'mount'
reports this line:
/dev/share on /share type 9p 
(rw,sync,dirsync,relatime,access=client,trans=virtio)
I see several test failures:

FAIL: test-fchdir
FAIL: test-fstatat
FAIL: test-getcwd-lgpl
FAIL: test-getcwd.sh
FAIL: test-linkat
FAIL: test-renameat
FAIL: test-renameatu
FAIL: test-stat
FAIL: test-statat

The cause is that the configure test in getcwd-path-max.m4 has experienced
an unexpected errno value:

  ...
  mkdirat(AT_FDCWD, "confdir3", 0700)     = 0
  chdir("confdir3")                       = 0
  mkdirat(AT_FDCWD, "confdir3", 0700)     = -1 EINVAL (Invalid argument)
  unlinkat(AT_FDCWD, "confdir3", AT_REMOVEDIR) = -1 ENOENT (No such file or 
directory)
  chdir("..")                             = 0
  ...

leading to an exit code of 20.

As a consequence, the normal glibc / system call getcwd(), which would succeed:

  getcwd("/share/home/bruno", 4096)       = 18

is overridden by a gnulib getcwd(), which fails:

  newfstatat(AT_FDCWD, ".", {st_mode=S_IFREG|071600022, st_size=0, ...}, 
AT_SYMLINK_NOFOLLOW) = 0
  newfstatat(AT_FDCWD, "/", {st_mode=002, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) 
= 0
  openat(AT_FDCWD, "..", O_RDONLY|O_LARGEFILE) = 3
  fstat(3, {st_mode=S_IFREG|071600015, st_size=0, ...}) = 0
  fstat(3, {st_mode=S_IFREG|071600015, st_size=0, ...}) = 0
  fcntl(3, F_GETFL)                       = 0x8000 (flags O_RDONLY|O_LARGEFILE)
  fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
  getdents64(3, 0x15190, 32768)           = -1 EPROTO (Protocol error)
  close(3)                                = 0

It's not required to investigate the precise cause of this EPROTO error;
we know that on Linux the getcwd() system call is good and that therefore
the gnulib getcwd() override is suboptimal.

This patch fixes the issue.

[1] https://www.kernel.org/doc/Documentation/filesystems/9p.txt


2019-01-13  Bruno Haible  <address@hidden>

        getcwd: Fix test failure when building on a Linux 9p file system.
        * m4/getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): On Linux, treat error
        EINVAL from mkdir like ENAMETOOLONG.
        * tests/test-getcwd.c (test_long_name): Likewise.

diff --git a/m4/getcwd-path-max.m4 b/m4/getcwd-path-max.m4
index 2cefc00..0ae3e1e 100644
--- a/m4/getcwd-path-max.m4
+++ b/m4/getcwd-path-max.m4
@@ -1,4 +1,4 @@
-# serial 21
+# serial 22
 # Check for several getcwd bugs with long file names.
 # If so, arrange to compile the wrapper function.
 
@@ -111,12 +111,20 @@ main ()
       /* If mkdir or chdir fails, it could be that this system cannot create
          any file with an absolute name longer than PATH_MAX, such as cygwin.
          If so, leave fail as 0, because the current working directory can't
-         be too long for getcwd if it can't even be created.  For other
-         errors, be pessimistic and consider that as a failure, too.  */
+         be too long for getcwd if it can't even be created.  On Linux with
+         the 9p file system, mkdir fails with error EINVAL when cwd_len gets
+         too long; ignore this failure because the getcwd() system call
+         produces good results whereas the gnulib substitute calls getdents64
+         which fails with error EPROTO.
+         For other errors, be pessimistic and consider that as a failure,
+         too.  */
       if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
         {
           if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
-            fail = 20;
+            #ifdef __linux__
+            if (! (errno == EINVAL))
+            #endif
+              fail = 20;
           break;
         }
 
diff --git a/tests/test-getcwd.c b/tests/test-getcwd.c
index 31c9037..b5f8155 100644
--- a/tests/test-getcwd.c
+++ b/tests/test-getcwd.c
@@ -166,12 +166,20 @@ test_long_name (void)
       /* If mkdir or chdir fails, it could be that this system cannot create
          any file with an absolute name longer than PATH_MAX, such as cygwin.
          If so, leave fail as 0, because the current working directory can't
-         be too long for getcwd if it can't even be created.  For other
-         errors, be pessimistic and consider that as a failure, too.  */
+         be too long for getcwd if it can't even be created.  On Linux with
+         the 9p file system, mkdir fails with error EINVAL when cwd_len gets
+         too long; ignore this failure because the getcwd() system call
+         produces good results whereas the gnulib substitute calls getdents64
+         which fails with error EPROTO.
+         For other errors, be pessimistic and consider that as a failure,
+         too.  */
       if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
         {
           if (! (errno == ERANGE || errno == ENAMETOOLONG || errno == ENOENT))
-            fail = 2;
+            #ifdef __linux__
+            if (! (errno == EINVAL))
+            #endif
+              fail = 2;
           break;
         }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]