summaryrefslogtreecommitdiff
path: root/lib/canonicalize-lgpl.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-12-17 01:22:55 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2020-12-17 01:39:46 -0800
commit8968aaa702c80a6d4c3af56e6892b5ad4359caf3 (patch)
treefc200873aa9192807493cac76e0107ea7b1467a1 /lib/canonicalize-lgpl.c
parent3a75362f0375f66ebe204c87313899ed81010731 (diff)
downloadgnulib-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.c39
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]))