bug#72547: [PATCH 4/9] filesys.c: Fix readlink for ports on Darwin.

Tomas Volf <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
When passed a port, `readlink' relies on the Linux specific behavior of
empty c_path meaning "the fd itself".  That does not work on Darwin.
Since there is no branch that would yield both fd and c_path, fallback
to freadlink when __APPLE__ is defined.

* libguile/filesys.c (do_readlink): Call freadlink for !__APPLE__.
* configure.ac (AC_CHECK_FUNCS): Add freadlink.
---
 configure.ac       |  2 +-
 libguile/filesys.c | 13 +++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 262b171f1..e6ed14220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -532,7 +532,7 @@ AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid         \
   fstatat futimens openat						\
   sched_getaffinity sched_setaffinity sendfile pipe2			\
   posix_spawn_file_actions_addclosefrom_np                              \
-  clearenv])
+  clearenv freadlink])
 
 # The newlib C library uses _NL_ prefixed locale langinfo constants.
 AC_CHECK_DECLS([_NL_NUMERIC_GROUPING], [], [], [[#include <langinfo.h>]])
diff --git a/libguile/filesys.c b/libguile/filesys.c
index 8657fedc3..8585005a9 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1192,14 +1192,23 @@ SCM_DEFINE (scm_symlinkat, "symlinkat", 3, 0, 0,
 #undef FUNC_NAME
 #endif /* HAVE_SYMLINKAT */
 
-/* Static helper function for choosing between readlink
+/* Static helper function for choosing between readlink, freadlink
    and readlinkat. */
 static int
 do_readlink (int fd, const char *c_path, char *buf, size_t size)
 {
-#ifdef HAVE_READLINKAT
+/* Darwin does not accept empty c_path. */
+#if HAVE_READLINKAT && !__APPLE__
   if (fd != -1)
     return readlinkat (fd, c_path, buf, size);
+#elif HAVE_FREADLINK
+  /* There is no branch in s_scm_readlink that would lead to having both fd and
+   * non-empty c_path.  Therefore if fd is set, we (on Darwin only) use
+   * freadlink and ignore the c_path.  On linux this case is already handled by
+   * readlinkat, but Darwin does not understand empty c_path to mean "the fd
+   * itself" the way Linux does. */
+  if (fd != -1)
+    return freadlink (fd, buf, size);
 #else
   (void) fd;
 #endif
-- 
2.45.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.