bug-gnulib
[Top][All Lists]
Advanced

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

Re: linkat test on AIX 7.1BETA


From: Bruno Haible
Subject: Re: linkat test on AIX 7.1BETA
Date: Sat, 31 Jul 2010 15:21:16 +0200
User-agent: KMail/1.9.9

Rainer Tammer wrote:

> AIX 7BETA:
> # ./testme
> ret = 0
> ret = 0

Yup. The expected result, as on Linux, is:

ret = -1
errno = 20
Not a directory
ret = -1
errno = 2
No such file or directory

I'm applying the patch below. Eric, if you don't agree, feel free to modify,
tweak, or revert it.

> P.S.: I just tried to regenerate the gnulib test from the current git.
> But I got an error at the end:
> 
> gperf -m 10 ./iconv_open-aix.gperf > ./iconv_open-aix.h-t
> /bin/sh: gperf:  not found.
> make: *** [iconv_open-aix.h] Error 127
> 
> So I have to get a working gperf ...

Yes. You find the complete list of required programs for using gnulib-tool
in the file gnulib/DEPENDENCIES.

> Could you please create a new gnulib test for me ?
> I really would like to use the new base.

Yes, I will do that, as soon as I've added fixes for all issues we have
encountered so far (except for strtod, ptsname, poll, utimens, utimensat).

Bruno


2010-07-31  Bruno Haible  <address@hidden>

        linkat: Work around AIX 7.1 bug.
        * m4/linkat.m4 (gl_FUNC_LINKAT): Require AC_CANONICAL_HOST. Test
        whether linkat handles trailing slash correctly. If not, replace linkat
        and define LINKAT_TRAILING_SLASH_BUG.
        * lib/linkat.c (rpl_linkat): If LINKAT_TRAILING_SLASH_BUG is defined,
        check whether (fd1,file1) points to a directory if file1 or file2 ends
        in a slash. Code taken from lib/link.c.
        * doc/posix-functions/linkat.texi: Mention trailing slash bug.

--- doc/posix-functions/linkat.texi.orig        Sat Jul 31 15:15:46 2010
+++ doc/posix-functions/linkat.texi     Sat Jul 31 14:11:11 2010
@@ -13,6 +13,10 @@
 glibc 2.3.6, MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX
 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, Interix 
3.5, BeOS.
 But the replacement function is not safe to be used in libraries and is not 
multithread-safe.
address@hidden
+This function fails to reject trailing slashes on non-directories on
+some platforms:
+AIX 7.1.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- lib/linkat.c.orig   Sat Jul 31 15:15:46 2010
+++ lib/linkat.c        Sat Jul 31 15:08:00 2010
@@ -262,14 +262,38 @@
 int
 rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
 {
-  if (!flag)
-    return linkat (fd1, file1, fd2, file2, flag);
   if (flag & ~AT_SYMLINK_FOLLOW)
     {
       errno = EINVAL;
       return -1;
     }
 
+#if LINKAT_TRAILING_SLASH_BUG
+  /* Reject trailing slashes on non-directories.  */
+  {
+    size_t len1 = strlen (file1);
+    size_t len2 = strlen (file2);
+    if ((len1 && file1[len1 - 1] == '/')
+        || (len2 && file2[len2 - 1] == '/'))
+      {
+        /* Let linkat() decide whether hard-linking directories is legal.
+           If fstatat() fails, then linkat() should fail for the same reason;
+           if fstatat() succeeds, require a directory.  */
+        struct stat st;
+        if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
+          return -1;
+        if (!S_ISDIR (st.st_mode))
+          {
+            errno = ENOTDIR;
+            return -1;
+          }
+      }
+  }
+#endif
+
+  if (!flag)
+    return linkat (fd1, file1, fd2, file2, flag);
+
   /* Cache the information on whether the system call really works.  */
   {
     static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
--- m4/linkat.m4.orig   Sat Jul 31 15:15:46 2010
+++ m4/linkat.m4        Sat Jul 31 15:00:13 2010
@@ -1,4 +1,4 @@
-# serial 2
+# serial 3
 # See if we need to provide linkat replacement.
 
 dnl Copyright (C) 2009-2010 Free Software Foundation, Inc.
@@ -15,6 +15,7 @@
   AC_REQUIRE([gl_FUNC_LINK_FOLLOWS_SYMLINK])
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
   AC_CHECK_FUNCS_ONCE([linkat symlink])
   AC_CHECK_HEADERS_ONCE([sys/param.h])
   if test $ac_cv_func_linkat = no; then
@@ -39,9 +40,60 @@
          [gl_cv_func_linkat_follow=yes],
          [gl_cv_func_linkat_follow="need runtime check"])
        rm -rf conftest.f1 conftest.f2])
-    if test "$gl_cv_func_linkat_follow" != yes; then
+    AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
+      [gl_cv_func_linkat_slash],
+      [rm -rf conftest.a conftest.b conftest.c conftest.d
+       AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <unistd.h>
+              #include <fcntl.h>
+              #include <errno.h>
+              #include <stdio.h>
+            ]],
+            [[int fd;
+              int err;
+              int ret;
+              /* Create a regular file.  */
+              fd = open ("conftest.a", O_CREAT | O_EXCL | O_WRONLY, 0600);
+              if (fd < 0)
+                return 1;
+              if (write (fd, "hello", 5) < 5)
+                return 2;
+              if (close (fd) < 0)
+                return 3;
+              /* Test whether hard links are supported on the current
+                 device.  */
+              if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.b",
+                          AT_SYMLINK_FOLLOW) < 0)
+                return 0;
+              /* Test whether a trailing "/" is treated like "/.".  */
+              if (linkat (AT_FDCWD, "conftest.a/", AT_FDCWD, "conftest.c",
+                          AT_SYMLINK_FOLLOW) == 0)
+                return 4;
+              if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.d/",
+                          AT_SYMLINK_FOLLOW) == 0)
+                return 5;
+              return 0;
+            ]])],
+         [gl_cv_func_linkat_slash=yes],
+         [gl_cv_func_linkat_slash=no],
+         [# Guess yes on glibc systems, no otherwise.
+          case "$host_os" in
+            *-gnu*) gl_cv_func_linkat_slash="guessing yes";;
+            *)      gl_cv_func_linkat_slash="guessing no";;
+          esac
+         ])
+       rm -rf conftest.a conftest.b conftest.c conftest.d])
+    case "$gl_cv_func_linkat_slash" in
+      *yes) gl_linkat_slash_bug=0 ;;
+      *)    gl_linkat_slash_bug=1 ;;
+    esac
+    if test "$gl_cv_func_linkat_follow" != yes \
+       || test $gl_linkat_slash_bug = 1; then
       REPLACE_LINKAT=1
       AC_LIBOBJ([linkat])
+      AC_DEFINE_UNQUOTED([LINKAT_TRAILING_SLASH_BUG], [$gl_linkat_slash_bug],
+        [Define to 1 if linkat fails to recognize a trailing slash.])
     fi
   fi
 ])



reply via email to

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