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.
2020-12-17 Paul Eggert <eggert@cs.ucla.edu>
+ 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
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <scratch_buffer.h>
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 ())
{
dest++;
}
}
+ else if (! (startlen == 0
+ ? stat (rname, &st) == 0 || errno == EOVERFLOW
+ : errno == EINVAL))
+ goto error;
}
}
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
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