]> 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 23:24:43 +0000 (01:24 +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 eb9d3dc9308ac1ae305e9f04dcd58b90b02e7796..4e4f01eb035b49593f276351e2518e19f0653ac6 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 14bbb7f10ca44b0bf0542f4a3db3f65cf70c02b3..f4af30ebc42b231125538140dbeb7402d027b6b4 100644 (file)
@@ -1,5 +1,5 @@
 /* Read the contents of a symbolic link.
-   Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
@@ -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 f1d41d2b113be702dd1998e8967723a946de0e6f..e6edb80f87324431bfbf427f99da1c3f93ff1537 100644 (file)
@@ -1,5 +1,5 @@
-# readlink.m4 serial 17
-dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+# 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,
 dnl with or without modifications, as long as this notice is preserved.
@@ -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 9d249dff54299cbde4d737c08df9eed7f3617ec2..ad5a275c43e2277ddf5bdf3a475ef43fc08e2ed0 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of execution of file name canonicalization.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
@@ -279,6 +279,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 8c5207ff7d1a441d94fc1e67c8936892c11b40d2..f7c9a47495b3eb7a4b3c9fa0c854717da1f2d35b 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of execution of file name canonicalization.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
@@ -413,6 +413,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);