]> Savannah Git Hosting - gnulib.git/commitdiff
readlink: Work around a Cygwin 3.3.6 bug.
authorBruno Haible <bruno@clisp.org>
Mon, 3 Jun 2024 23:48:04 +0000 (01:48 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 6 Jun 2024 22:55:43 +0000 (00:55 +0200)
* m4/readlink.m4 (gl_FUNC_READLINK): Set REPLACE_READLINK to 1 on Cygwin.
* lib/readlink.c (rpl_readlink): On Cygwin, for /dev/* files, don't
return results that start with a backslash.
* tests/test-readlink.h (test_readlink): Add a test of /dev/null.
* tests/test-canonicalize-lgpl.c (main): Likewise.
* tests/test-canonicalize.c (main): Likewise.
* doc/posix-functions/readlink.texi: Mention the Cygwin bug.

ChangeLog
doc/posix-functions/readlink.texi
lib/readlink.c
m4/readlink.m4
tests/test-canonicalize-lgpl.c
tests/test-canonicalize.c
tests/test-readlink.h

index 3985d66d3765b053728f1b9e2734251b15e55531..06c0e34ce2773b565482e7be2a056996aed0cec1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2024-06-03  Bruno Haible  <bruno@clisp.org>
+
+       readlink: Work around a Cygwin 3.3.6 bug.
+       * m4/readlink.m4 (gl_FUNC_READLINK): Set REPLACE_READLINK to 1 on Cygwin.
+       * lib/readlink.c (rpl_readlink): On Cygwin, for /dev/* files, don't
+       return results that start with a backslash.
+       * tests/test-readlink.h (test_readlink): Add a test of /dev/null.
+       * tests/test-canonicalize-lgpl.c (main): Likewise.
+       * tests/test-canonicalize.c (main): Likewise.
+       * doc/posix-functions/readlink.texi: Mention the Cygwin bug.
+
 2024-06-03  Bruno Haible  <bruno@clisp.org>
 
        nstrftime tests: Avoid some failures on native Windows.
index d4421380a8e333b49136539d9d527dd8cb9023a9..732349ea15bc6c2921023b096b8ba042f40938ae 100644 (file)
@@ -18,6 +18,10 @@ FreeBSD 7.2, Solaris 9, Mac OS X 10.10.
 On some platforms, this function returns @code{int} instead of
 @code{ssize_t}:
 glibc 2.4, FreeBSD 6.0, OpenBSD 6.7, Cygwin 1.5.x, AIX 7.1.
+@item
+For the file name @file{/dev/null}, this function returns @file{\Device\Null},
+which is unusable, on some platforms:
+Cygwin 3.3.6.
 @end itemize
 
 Portability problems mostly fixed by Gnulib:
index a5369fa977b8567c28122aed3f711bd3d5d0f5e9..f4af30ebc42b231125538140dbeb7402d027b6b4 100644 (file)
@@ -98,6 +98,16 @@ rpl_readlink (char const *file, char *buf, size_t bufsize)
     }
 # endif
 
+# if defined __CYGWIN__
+  /* On Cygwin 3.3.6, readlink("/dev/null") returns "\\Device\\Null", which
+     is unusable.  Better fail with EINVAL.  */
+  if (r > 0 && strncmp (file, "/dev/", 5) == 0 && buf[0] == '\\')
+    {
+      errno = EINVAL;
+      return -1;
+    }
+# endif
+
   return r;
 }
 
index 6d78ec84a03da30585bb32d5f86ebc05ebe6cabe..e6edb80f87324431bfbf427f99da1c3f93ff1537 100644 (file)
@@ -1,4 +1,4 @@
-# readlink.m4 serial 17
+# readlink.m4 serial 18
 dnl Copyright (C) 2003, 2007, 2009-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
 AC_DEFUN([gl_FUNC_READLINK],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
-  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([readlink])
   if test $ac_cv_func_readlink = no; then
     HAVE_READLINK=0
@@ -17,9 +17,13 @@ AC_DEFUN([gl_FUNC_READLINK],
       [AC_COMPILE_IFELSE(
          [AC_LANG_PROGRAM(
            [[#include <unistd.h>
-      /* Cause compilation failure if original declaration has wrong type.  */
-      ssize_t readlink (const char *, char *, size_t);]])],
+             /* Cause compilation failure if original declaration has
+                wrong type.  */
+             ssize_t readlink (const char *, char *, size_t);
+           ]])
+         ],
          [gl_cv_decl_readlink_works=yes], [gl_cv_decl_readlink_works=no])])
+
     dnl Solaris 9 ignores trailing slash.
     dnl FreeBSD 7.2 dereferences only one level of links with trailing slash.
     AC_CACHE_CHECK([whether readlink handles trailing slash correctly],
@@ -30,8 +34,11 @@ AC_DEFUN([gl_FUNC_READLINK],
        AC_RUN_IFELSE(
          [AC_LANG_PROGRAM(
            [[#include <unistd.h>
-]], [[char buf[20];
-      return readlink ("conftest.lnk2/", buf, sizeof buf) != -1;]])],
+           ]],
+           [[char buf[20];
+             return readlink ("conftest.lnk2/", buf, sizeof buf) != -1;
+           ]])
+         ],
          [gl_cv_func_readlink_trailing_slash=yes],
          [gl_cv_func_readlink_trailing_slash=no],
          [case "$host_os" in
@@ -70,8 +77,11 @@ AC_DEFUN([gl_FUNC_READLINK],
        AC_RUN_IFELSE(
          [AC_LANG_PROGRAM(
            [[#include <unistd.h>
-]], [[char c;
-      return readlink ("conftest.link", &c, 1) != 1;]])],
+           ]],
+           [[char c;
+             return readlink ("conftest.link", &c, 1) != 1;
+           ]])
+         ],
          [gl_cv_func_readlink_truncate=yes],
          [gl_cv_func_readlink_truncate=no],
          [case "$host_os" in
@@ -102,6 +112,14 @@ AC_DEFUN([gl_FUNC_READLINK],
         REPLACE_READLINK=1
         ;;
     esac
+
+    dnl On Cygwin 3.3.6, readlink("/dev/null") returns "\\Device\\Null", which
+    dnl is unusable.
+    case "$host_os" in
+      cygwin*)
+        REPLACE_READLINK=1
+        ;;
+    esac
   fi
 ])
 
index 21211e5eac4d5565301e114a9267ed3b18ce036a..921fdbde70b2d4d476f268a0310987c9f3ad7b87 100644 (file)
@@ -281,6 +281,13 @@ main (void)
     free (result2);
   }
 
+#if !(defined _WIN32 && !defined __CYGWIN__)
+  /* Check a device file.  */
+  {
+    char *result = canonicalize_file_name ("/dev/null");
+    ASSERT (result != NULL);
+  }
+#endif
 
   /* Cleanup.  */
   ASSERT (remove (BASE "/droot") == 0);
index 5d19285c009b012b6b6a2d449a1310c0e90d4a9e..1ef7bb3959a7ca80feaa7f2e394723751cfd733b 100644 (file)
@@ -419,6 +419,17 @@ main (void)
     free (result4);
   }
 
+#if !(defined _WIN32 && !defined __CYGWIN__)
+  /* Check a device file.  */
+  {
+    char *result1 = canonicalize_file_name ("/dev/null");
+    char *result2 = canonicalize_filename_mode ("/dev/null", CAN_ALL_BUT_LAST);
+    ASSERT (result1 != NULL);
+    ASSERT (result2 != NULL);
+    ASSERT (strcmp (result1, result2) == 0);
+  }
+#endif
+
   /* Cleanup.  */
   ASSERT (remove (BASE "/droot") == 0);
   ASSERT (remove (BASE "/d/1") == 0);
index c04ae311e2676da1ecb86b294538448e35ee8dd3..d547bec959122c390a77f85c6b7021eb25452e40 100644 (file)
@@ -113,6 +113,12 @@ test_readlink (ssize_t (*func) (char const *, char *, size_t), bool print)
        either left alone, or NUL-terminated.  */
     ASSERT (buf[len] == '\0' || buf[len] == (char) 0xff);
   }
+  {
+    /* On Cygwin 3.3.6, readlink("/dev/null") returns "\\Device\\Null", which
+       is unusable.  Verify that gnulib works around this nonsense.  */
+    ssize_t result = func ("/dev/null", buf, sizeof buf);
+    ASSERT (result == -1 || buf[0] != '\\');
+  }
   ASSERT (rmdir (BASE "dir") == 0);
   ASSERT (unlink (BASE "link") == 0);