From 2fb0446d5b4f410608adcfe3297338bdeef23abe Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Wed, 10 Mar 2021 12:07:01 +0100 Subject: [PATCH 03/17] =?UTF-8?q?Allow=20file=20ports=20in=20=E2=80=98read?= =?UTF-8?q?link=E2=80=99.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * configure.ac: Detect whether ‘readlinkat’ is defined. * libguile/filesys.c (scm_readlink): Support file ports when ‘readlinkat’ exists. * doc/ref/posix.texi (File System): Document it. --- configure.ac | 2 +- doc/ref/posix.texi | 3 ++- libguile/filesys.c | 45 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index a23249d95..0f032272a 100644 --- a/configure.ac +++ b/configure.ac @@ -481,7 +481,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h]) # sendfile - non-POSIX, found in glibc # AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \ - fesetround ftime ftruncate fchown fchmod fchdir \ + fesetround ftime ftruncate fchown fchmod fchdir readlinkat \ getcwd geteuid getsid \ gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mkdtemp mknod \ nice readlink rename rmdir setegid seteuid \ diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi index 54c564cb0..68de5a2ed 100644 --- a/doc/ref/posix.texi +++ b/doc/ref/posix.texi @@ -795,7 +795,8 @@ file it points to. @var{path} must be a string. @deffn {Scheme Procedure} readlink path @deffnx {C Function} scm_readlink (path) Return the value of the symbolic link named by @var{path} (a -string), i.e., the file that the link points to. +string, or a port if the @code{readlinkat} system call is supported), +i.e., the file that the link points to. @end deffn @findex fchown diff --git a/libguile/filesys.c b/libguile/filesys.c index a8879f0e1..06a550fc8 100644 --- a/libguile/filesys.c +++ b/libguile/filesys.c @@ -1081,10 +1081,25 @@ SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0, #undef FUNC_NAME #endif /* HAVE_SYMLINK */ -SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0, +/* Static helper function for choosing between readlink + and readlinkat. */ +static int +do_readlink (int fd, const char *c_path, char *buf, size_t size) +{ +#ifdef HAVE_READLINKAT + if (fd != -1) + return readlinkat (fd, c_path, buf, size); +#else + (void) fd; +#endif + return readlink (c_path, buf, size); +} + +SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0, (SCM path), - "Return the value of the symbolic link named by @var{path} (a\n" - "string), i.e., the file that the link points to.") + "Return the value of the symbolic link named by @var{path} (a\n" + "string, or a port if the @code{readlinkat} system call is supported),\n" + "i.e., the file that the link points to.") #define FUNC_NAME s_scm_readlink { int rv; @@ -1092,20 +1107,32 @@ SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0, char *buf; SCM result; char *c_path; - - scm_dynwind_begin (0); - - c_path = scm_to_locale_string (path); - scm_dynwind_free (c_path); + int fdes; + scm_dynwind_begin (0); +#ifdef HAVE_READLINKAT + if (SCM_FPORTP (path)) + { + SCM_VALIDATE_OPINPORT (SCM_ARG1, path); + c_path = ""; + fdes = SCM_FPORT_FDES (path); + } + else +#endif + { + fdes = -1; + c_path = scm_to_locale_string (path); + scm_dynwind_free (c_path); + } buf = scm_malloc (size); - while ((rv = readlink (c_path, buf, size)) == size) + while ((rv = do_readlink (fdes, c_path, buf, size)) == size) { free (buf); size *= 2; buf = scm_malloc (size); } + scm_remember_upto_here_1 (path); if (rv == -1) { int save_errno = errno; -- 2.30.2