From 8968aaa702c80a6d4c3af56e6892b5ad4359caf3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 17 Dec 2020 01:22:55 -0800 Subject: [PATCH 4/4] canonicalize-lgpl: fix AIX test failures This merges the recent canonicalize.c fix into canonicalize-lgpl.c. Problem reported by Bruno Haible in: https://lists.gnu.org/r/bug-gnulib/2020-12/msg00138.html * lib/canonicalize-lgpl.c: Include sys/stat.h. (__realpath): When testing a file name ending in '/', use stat rather than readlink, so that it does the right thing on AIX. * modules/canonicalize-lgpl (Depends-on): Add stat, sys_stat. --- ChangeLog | 9 +++++++++ lib/canonicalize-lgpl.c | 39 ++++++++++++++++++++++++--------------- modules/canonicalize-lgpl | 2 ++ 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index fccedabe3..74f2ceb34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2020-12-17 Paul Eggert + canonicalize-lgpl: fix AIX test failures + This merges the recent canonicalize.c fix into canonicalize-lgpl.c. + Problem reported by Bruno Haible in: + https://lists.gnu.org/r/bug-gnulib/2020-12/msg00138.html + * lib/canonicalize-lgpl.c: Include sys/stat.h. + (__realpath): When testing a file name ending in '/', use stat + rather than readlink, so that it does the right thing on AIX. + * modules/canonicalize-lgpl (Depends-on): Add stat, sys_stat. + canonicalize: omit second readlink when not needed * lib/canonicalize.c (canonicalize_filename_mode_stk): Omit second readlink when (can_exist != CAN_MISSING diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c index 2c86330c0..1440dad34 100644 --- a/lib/canonicalize-lgpl.c +++ b/lib/canonicalize-lgpl.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -237,24 +238,28 @@ __realpath (const char *name, char *resolved) dest = __mempcpy (dest, start, startlen); *dest = '\0'; + /* If STARTLEN == 0, RNAME ends in '/'; use stat rather than + readlink, because readlink might fail with EINVAL without + checking whether RNAME sans '/' is valid. */ + struct stat st; + char *buf = NULL; ssize_t n; - char *buf; - while (true) + if (startlen != 0) { - buf = link_buffer.data; - idx_t bufsize = link_buffer.length; - n = __readlink (rname, buf, bufsize - 1); - if (n < bufsize - 1) - break; - if (!scratch_buffer_grow (&link_buffer)) - goto error_nomem; - } - if (n < 0) - { - if (errno != EINVAL) - goto error; + while (true) + { + buf = link_buffer.data; + idx_t bufsize = link_buffer.length; + n = __readlink (rname, buf, bufsize - 1); + if (n < bufsize - 1) + break; + if (!scratch_buffer_grow (&link_buffer)) + goto error_nomem; + } + if (n < 0) + buf = NULL; } - else + if (buf) { if (++num_links > __eloop_threshold ()) { @@ -310,6 +315,10 @@ __realpath (const char *name, char *resolved) dest++; } } + else if (! (startlen == 0 + ? stat (rname, &st) == 0 || errno == EOVERFLOW + : errno == EINVAL)) + goto error; } } if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1])) diff --git a/modules/canonicalize-lgpl b/modules/canonicalize-lgpl index 9cd3df7bb..d4dfcc905 100644 --- a/modules/canonicalize-lgpl +++ b/modules/canonicalize-lgpl @@ -23,7 +23,9 @@ pathmax [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONI rawmemchr [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] readlink [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] scratch_buffer [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] +stat [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] stdbool [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] +sys_stat [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1] configure.ac: gl_CANONICALIZE_LGPL -- 2.27.0