diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2020-12-17 01:22:55 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2020-12-17 01:39:46 -0800 |
commit | 8968aaa702c80a6d4c3af56e6892b5ad4359caf3 (patch) | |
tree | fc200873aa9192807493cac76e0107ea7b1467a1 /lib/canonicalize-lgpl.c | |
parent | 3a75362f0375f66ebe204c87313899ed81010731 (diff) | |
download | gnulib-8968aaa702c80a6d4c3af56e6892b5ad4359caf3.tar.gz |
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.
Diffstat (limited to 'lib/canonicalize-lgpl.c')
-rw-r--r-- | lib/canonicalize-lgpl.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c index 2c86330c05..1440dad343 100644 --- a/lib/canonicalize-lgpl.c +++ b/lib/canonicalize-lgpl.c @@ -33,6 +33,7 @@ #include <stdbool.h> #include <stddef.h> #include <string.h> +#include <sys/stat.h> #include <unistd.h> #include <scratch_buffer.h> @@ -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])) |