mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 12:35:55 +08:00
5e8754f90a
This reverts commit 7a6dbc2fdb
("Update
gnulib to current upstream master"). It is needed because the gnulib
update caused problems with people using old GCC compilers (version
4.8, for example), which support C99 but don't default to using it.
Unfortunately this broke GDB for these users. A more detailed report
of what happened can be found at:
https://lists.gnu.org/archive/html/bug-gnulib/2018-08/msg00157.html
The reason for updating our gnulib copy was to fix PR gdb/23558.
Reverting this patch reintroduces the bug, so in order to fix it I
will submit a subsequent patch which cherry-picks the fix from gnulib.
gdb/ChangeLog:
2018-09-10 Sergio Durigan Junior <sergiodj@redhat.com>
Revert:
2018-08-29 Sergio Durigan Junior <sergiodj@redhat.com>
PR gdb/23555
PR gdb/23558
* gnulib/aclocal.m4: Regenerate.
* gnulib/config.in: Regenerate.
* gnulib/configure: Regenerate.
* gnulib/import/Makefile.am: Update.
* gnulib/import/Makefile.in: Update.
* gnulib/import/extra/snippet/_Noreturn.h: Rename to...
* gnulib/import/_Noreturn.h: ... this.
* gnulib/import/alloca.in.h: Update.
* gnulib/import/extra/snippet/arg-nonnull.h: Rename to...
* gnulib/import/arg-nonnull.h: ... this.
* gnulib/import/assure.h: Update.
* gnulib/import/at-func.c: Update.
* gnulib/import/basename-lgpl.c: Update.
* gnulib/import/extra/snippet/c++defs.h: Rename to...
* gnulib/import/c++defs.h: ... this.
* gnulib/import/canonicalize-lgpl.c: Update.
* gnulib/import/cdefs.h: Update.
* gnulib/import/chdir-long.c: Update.
* gnulib/import/chdir-long.h: Update.
* gnulib/import/cloexec.c: Update.
* gnulib/import/cloexec.h: Update.
* gnulib/import/close.c: Update.
* gnulib/import/closedir.c: Update.
* gnulib/import/config.charset: Update.
* gnulib/import/dirent-private.h: Update.
* gnulib/import/dirent.in.h: Update.
* gnulib/import/dirfd.c: Update.
* gnulib/import/dirname-lgpl.c: Update.
* gnulib/import/dirname.h: Update.
* gnulib/import/dosname.h: Update.
* gnulib/import/dup-safer-flag.c: Update.
* gnulib/import/dup-safer.c: Update.
* gnulib/import/dup.c: Update.
* gnulib/import/dup2.c: Update.
* gnulib/import/errno.in.h: Update.
* gnulib/import/error.c: Update.
* gnulib/import/error.h: Update.
* gnulib/import/exitfail.c: Update.
* gnulib/import/exitfail.h: Update.
* gnulib/import/extra/update-copyright: Update.
* gnulib/import/fchdir.c: Update.
* gnulib/import/fcntl.c: Update.
* gnulib/import/fcntl.in.h: Update.
* gnulib/import/fd-hook.c: Update.
* gnulib/import/fd-hook.h: Update.
* gnulib/import/fd-safer-flag.c: Update.
* gnulib/import/fd-safer.c: Update.
* gnulib/import/fdopendir.c: Update.
* gnulib/import/filename.h: Update.
* gnulib/import/filenamecat-lgpl.c: Update.
* gnulib/import/filenamecat.h: Update.
* gnulib/import/flexmember.h: Update.
* gnulib/import/float+.h: Update.
* gnulib/import/float.c: Update.
* gnulib/import/float.in.h: Update.
* gnulib/import/fnmatch.c: Update.
* gnulib/import/fnmatch.in.h: Update.
* gnulib/import/fnmatch_loop.c: Update.
* gnulib/import/fpucw.h: Update.
* gnulib/import/frexp.c: Update.
* gnulib/import/frexpl.c: Update.
* gnulib/import/fstat.c: Update.
* gnulib/import/fstatat.c: Update.
* gnulib/import/getcwd-lgpl.c: Update.
* gnulib/import/getcwd.c: Update.
* gnulib/import/getdtablesize.c: Update.
* gnulib/import/getlogin_r.c: Update.
* gnulib/import/getprogname.c: Update.
* gnulib/import/getprogname.h: Update.
* gnulib/import/gettext.h: Update.
* gnulib/import/gettimeofday.c: Update.
* gnulib/import/glob-libc.h: Update.
* gnulib/import/glob.c: Update.
* gnulib/import/glob.in.h: Update.
* gnulib/import/glob_internal.h: Update.
* gnulib/import/glob_pattern_p.c: Update.
* gnulib/import/globfree.c: Update.
* gnulib/import/hard-locale.c: Update.
* gnulib/import/hard-locale.h: Update.
* gnulib/import/intprops.h: Update.
* gnulib/import/inttypes.in.h: Update.
* gnulib/import/isnan.c: Update.
* gnulib/import/isnand-nolibm.h: Update.
* gnulib/import/isnand.c: Update.
* gnulib/import/isnanl-nolibm.h: Update.
* gnulib/import/isnanl.c: Update.
* gnulib/import/itold.c: Update.
* gnulib/import/libc-config.h: Update.
* gnulib/import/limits.in.h: Update.
* gnulib/import/localcharset.c: Update.
* gnulib/import/localcharset.h: Update.
* gnulib/import/localtime-buffer.c: Update.
* gnulib/import/localtime-buffer.h: Update.
* gnulib/import/lstat.c: Update.
* gnulib/import/m4/00gnulib.m4: Update.
* gnulib/import/m4/__inline.m4: Update.
* gnulib/import/m4/absolute-header.m4: Update.
* gnulib/import/m4/alloca.m4: Update.
* gnulib/import/m4/builtin-expect.m4: Update.
* gnulib/import/m4/canonicalize.m4: Update.
* gnulib/import/m4/chdir-long.m4: Update.
* gnulib/import/m4/close.m4: Update.
* gnulib/import/m4/closedir.m4: Update.
* gnulib/import/m4/configmake.m4: Update.
* gnulib/import/m4/d-ino.m4: Update.
* gnulib/import/m4/d-type.m4: Update.
* gnulib/import/m4/dirent_h.m4: Update.
* gnulib/import/m4/dirfd.m4: Update.
* gnulib/import/m4/dirname.m4: Update.
* gnulib/import/m4/double-slash-root.m4: Update.
* gnulib/import/m4/dup.m4: Update.
* gnulib/import/m4/dup2.m4: Update.
* gnulib/import/m4/eealloc.m4: Update.
* gnulib/import/m4/environ.m4: Update.
* gnulib/import/m4/errno_h.m4: Update.
* gnulib/import/m4/error.m4: Update.
* gnulib/import/m4/exponentd.m4: Update.
* gnulib/import/m4/exponentl.m4: Update.
* gnulib/import/m4/extensions.m4: Update.
* gnulib/import/m4/extern-inline.m4: Update.
* gnulib/import/m4/fchdir.m4: Update.
* gnulib/import/m4/fcntl-o.m4: Update.
* gnulib/import/m4/fcntl.m4: Update.
* gnulib/import/m4/fcntl_h.m4: Update.
* gnulib/import/m4/fdopendir.m4: Update.
* gnulib/import/m4/filenamecat.m4: Update.
* gnulib/import/m4/flexmember.m4: Update.
* gnulib/import/m4/float_h.m4: Update.
* gnulib/import/m4/fnmatch.m4: Update.
* gnulib/import/m4/fnmatch_h.m4: Update.
* gnulib/import/m4/fpieee.m4: Update.
* gnulib/import/m4/frexp.m4: Update.
* gnulib/import/m4/frexpl.m4: Update.
* gnulib/import/m4/fstat.m4: Update.
* gnulib/import/m4/fstatat.m4: Update.
* gnulib/import/m4/getcwd-abort-bug.m4: Update.
* gnulib/import/m4/getcwd-path-max.m4: Update.
* gnulib/import/m4/getcwd.m4: Update.
* gnulib/import/m4/getdtablesize.m4: Update.
* gnulib/import/m4/getlogin.m4: Update.
* gnulib/import/m4/getlogin_r.m4: Update.
* gnulib/import/m4/getpagesize.m4: Update.
* gnulib/import/m4/getprogname.m4: Update.
* gnulib/import/m4/gettimeofday.m4: Update.
* gnulib/import/m4/glibc21.m4: Update.
* gnulib/import/m4/glob.m4: Update.
* gnulib/import/m4/glob_h.m4: Update.
* gnulib/import/m4/gnulib-cache.m4: Update.
* gnulib/import/m4/gnulib-common.m4: Update.
* gnulib/import/m4/gnulib-comp.m4: Update.
* gnulib/import/m4/gnulib-tool.m4: Update.
* gnulib/import/m4/hard-locale.m4: Update.
* gnulib/import/m4/include_next.m4: Update.
* gnulib/import/m4/inttypes-pri.m4: Update.
* gnulib/import/m4/inttypes.m4: Update.
* gnulib/import/m4/isnand.m4: Update.
* gnulib/import/m4/isnanl.m4: Update.
* gnulib/import/m4/largefile.m4: Update.
* gnulib/import/m4/limits-h.m4: Update.
* gnulib/import/m4/localcharset.m4: Update.
* gnulib/import/m4/locale-fr.m4: Update.
* gnulib/import/m4/locale-ja.m4: Update.
* gnulib/import/m4/locale-zh.m4: Update.
* gnulib/import/m4/localtime-buffer.m4: Update.
* gnulib/import/m4/longlong.m4: Update.
* gnulib/import/m4/lstat.m4: Update.
* gnulib/import/m4/malloc.m4: Update.
* gnulib/import/m4/malloca.m4: Update.
* gnulib/import/m4/math_h.m4: Update.
* gnulib/import/m4/mbrtowc.m4: Update.
* gnulib/import/m4/mbsinit.m4: Update.
* gnulib/import/m4/mbsrtowcs.m4: Update.
* gnulib/import/m4/mbstate_t.m4: Update.
* gnulib/import/m4/memchr.m4: Update.
* gnulib/import/m4/memmem.m4: Update.
* gnulib/import/m4/mempcpy.m4: Update.
* gnulib/import/m4/memrchr.m4: Update.
* gnulib/import/m4/mkdir.m4: Update.
* gnulib/import/m4/mkstemp.m4: Update.
* gnulib/import/m4/mmap-anon.m4: Update.
* gnulib/import/m4/mode_t.m4: Update.
* gnulib/import/m4/msvc-inval.m4: Update.
* gnulib/import/m4/msvc-nothrow.m4: Update.
* gnulib/import/m4/multiarch.m4: Update.
* gnulib/import/m4/nocrash.m4: Update.
* gnulib/import/m4/off_t.m4: Update.
* gnulib/import/m4/onceonly.m4: Update.
* gnulib/import/m4/open-cloexec.m4: Update.
* gnulib/import/m4/open.m4: Update.
* gnulib/import/m4/openat.m4: Update.
* gnulib/import/m4/opendir.m4: Update.
* gnulib/import/m4/pathmax.m4: Update.
* gnulib/import/m4/rawmemchr.m4: Update.
* gnulib/import/m4/readdir.m4: Update.
* gnulib/import/m4/readlink.m4: Update.
* gnulib/import/m4/realloc.m4: Update.
* gnulib/import/m4/rename.m4: Update.
* gnulib/import/m4/rewinddir.m4: Update.
* gnulib/import/m4/rmdir.m4: Update.
* gnulib/import/m4/save-cwd.m4: Update.
* gnulib/import/m4/secure_getenv.m4: Update.
* gnulib/import/m4/setenv.m4: Update.
* gnulib/import/m4/signal_h.m4: Update.
* gnulib/import/m4/ssize_t.m4: Update.
* gnulib/import/m4/stat-time.m4: Update.
* gnulib/import/m4/stat.m4: Update.
* gnulib/import/m4/std-gnu11.m4: Update.
* gnulib/import/m4/stdbool.m4: Update.
* gnulib/import/m4/stddef_h.m4: Update.
* gnulib/import/m4/stdint.m4: Update.
* gnulib/import/m4/stdio_h.m4: Update.
* gnulib/import/m4/stdlib_h.m4: Update.
* gnulib/import/m4/strchrnul.m4: Update.
* gnulib/import/m4/strdup.m4: Update.
* gnulib/import/m4/strerror.m4: Update.
* gnulib/import/m4/string_h.m4: Update.
* gnulib/import/m4/strstr.m4: Update.
* gnulib/import/m4/strtok_r.m4: Update.
* gnulib/import/m4/sys_socket_h.m4: Update.
* gnulib/import/m4/sys_stat_h.m4: Update.
* gnulib/import/m4/sys_time_h.m4: Update.
* gnulib/import/m4/sys_types_h.m4: Update.
* gnulib/import/m4/tempname.m4: Update.
* gnulib/import/m4/time_h.m4: Update.
* gnulib/import/m4/unistd-safer.m4: Update.
* gnulib/import/m4/unistd_h.m4: Update.
* gnulib/import/m4/warn-on-use.m4: Update.
* gnulib/import/m4/wchar_h.m4: Update.
* gnulib/import/m4/wchar_t.m4: Update.
* gnulib/import/m4/wctype_h.m4: Update.
* gnulib/import/m4/wint_t.m4: Update.
* gnulib/import/malloc.c: Update.
* gnulib/import/malloc/scratch_buffer.h: Update.
* gnulib/import/malloc/scratch_buffer_grow.c: Update.
* gnulib/import/malloc/scratch_buffer_grow_preserve.c: Update.
* gnulib/import/malloc/scratch_buffer_set_array_size.c: Update.
* gnulib/import/malloca.c: Update.
* gnulib/import/malloca.h: Update.
* gnulib/import/malloca.valgrind: Update.
* gnulib/import/math.in.h: Update.
* gnulib/import/mbrtowc.c: Update.
* gnulib/import/mbsinit.c: Update.
* gnulib/import/mbsrtowcs-impl.h: Update.
* gnulib/import/mbsrtowcs-state.c: Update.
* gnulib/import/mbsrtowcs.c: Update.
* gnulib/import/memchr.c: Update.
* gnulib/import/memmem.c: Update.
* gnulib/import/mempcpy.c: Update.
* gnulib/import/memrchr.c: Update.
* gnulib/import/mkdir.c: Update.
* gnulib/import/mkstemp.c: Update.
* gnulib/import/msvc-inval.c: Update.
* gnulib/import/msvc-inval.h: Update.
* gnulib/import/msvc-nothrow.c: Update.
* gnulib/import/msvc-nothrow.h: Update.
* gnulib/import/open.c: Update.
* gnulib/import/openat-die.c: Update.
* gnulib/import/openat-priv.h: Update.
* gnulib/import/openat-proc.c: Update.
* gnulib/import/openat.c: Update.
* gnulib/import/openat.h: Update.
* gnulib/import/opendir.c: Update.
* gnulib/import/pathmax.h: Update.
* gnulib/import/pipe-safer.c: Update.
* gnulib/import/rawmemchr.c: Update.
* gnulib/import/readdir.c: Update.
* gnulib/import/readlink.c: Update.
* gnulib/import/realloc.c: Update.
* gnulib/import/ref-add.sin: Update.
* gnulib/import/ref-del.sin: Update.
* gnulib/import/rename.c: Update.
* gnulib/import/rewinddir.c: Update.
* gnulib/import/rmdir.c: Update.
* gnulib/import/same-inode.h: Update.
* gnulib/import/save-cwd.c: Update.
* gnulib/import/save-cwd.h: Update.
* gnulib/import/scratch_buffer.h: Update.
* gnulib/import/secure_getenv.c: Update.
* gnulib/import/setenv.c: Update.
* gnulib/import/signal.in.h: Update.
* gnulib/import/stat-time.c: Update.
* gnulib/import/stat-time.h: Update.
* gnulib/import/stat-w32.c: Update.
* gnulib/import/stat-w32.h: Update.
* gnulib/import/stat.c: Update.
* gnulib/import/stdbool.in.h: Update.
* gnulib/import/stddef.in.h: Update.
* gnulib/import/stdint.in.h: Update.
* gnulib/import/stdio.in.h: Update.
* gnulib/import/stdlib.in.h: Update.
* gnulib/import/str-two-way.h: Update.
* gnulib/import/strchrnul.c: Update.
* gnulib/import/strdup.c: Update.
* gnulib/import/streq.h: Update.
* gnulib/import/strerror-override.c: Update.
* gnulib/import/strerror-override.h: Update.
* gnulib/import/strerror.c: Update.
* gnulib/import/string.in.h: Update.
* gnulib/import/stripslash.c: Update.
* gnulib/import/strnlen1.c: Update.
* gnulib/import/strnlen1.h: Update.
* gnulib/import/strstr.c: Update.
* gnulib/import/strtok_r.c: Update.
* gnulib/import/sys_stat.in.h: Update.
* gnulib/import/sys_time.in.h: Update.
* gnulib/import/sys_types.in.h: Update.
* gnulib/import/tempname.c: Update.
* gnulib/import/tempname.h: Update.
* gnulib/import/time.in.h: Update.
* gnulib/import/unistd--.h: Update.
* gnulib/import/unistd-safer.h: Update.
* gnulib/import/unistd.in.h: Update.
* gnulib/import/unsetenv.c: Update.
* gnulib/import/verify.h: Update.
* gnulib/import/extra/snippet/warn-on-use.h: Update.
* gnulib/import/wchar.in.h: Update.
* gnulib/import/wctype.in.h: Update.
* gnulib/import/xalloc-oversized.h: Update.
* gnulib/update-gnulib.sh (GNULIB_COMMIT_SHA1): Set to
"53e2c179f26a890fa6685af4b6c1397ee370433b".
425 lines
12 KiB
C
425 lines
12 KiB
C
/* Return the canonical absolute name of a given file.
|
|
Copyright (C) 1996-2016 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _LIBC
|
|
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
|
|
optimizes away the name == NULL test below. */
|
|
# define _GL_ARG_NONNULL(params)
|
|
|
|
# define _GL_USE_STDLIB_ALLOC 1
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
|
|
|
|
/* Specification. */
|
|
#include <stdlib.h>
|
|
|
|
#include <alloca.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
#if HAVE_SYS_PARAM_H || defined _LIBC
|
|
# include <sys/param.h>
|
|
#endif
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
|
|
#ifdef _LIBC
|
|
# include <shlib-compat.h>
|
|
#else
|
|
# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
|
|
# define versioned_symbol(lib, local, symbol, version) extern int dummy
|
|
# define compat_symbol(lib, local, symbol, version)
|
|
# define weak_alias(local, symbol)
|
|
# define __canonicalize_file_name canonicalize_file_name
|
|
# define __realpath realpath
|
|
# include "pathmax.h"
|
|
# include "malloca.h"
|
|
# include "dosname.h"
|
|
# if HAVE_GETCWD
|
|
# if IN_RELOCWRAPPER
|
|
/* When building the relocatable program wrapper, use the system's getcwd
|
|
function, not the gnulib override, otherwise we would get a link error.
|
|
*/
|
|
# undef getcwd
|
|
# endif
|
|
# ifdef VMS
|
|
/* We want the directory in Unix syntax, not in VMS syntax. */
|
|
# define __getcwd(buf, max) getcwd (buf, max, 0)
|
|
# else
|
|
# define __getcwd getcwd
|
|
# endif
|
|
# else
|
|
# define __getcwd(buf, max) getwd (buf)
|
|
# endif
|
|
# define __readlink readlink
|
|
# define __set_errno(e) errno = (e)
|
|
# ifndef MAXSYMLINKS
|
|
# ifdef SYMLOOP_MAX
|
|
# define MAXSYMLINKS SYMLOOP_MAX
|
|
# else
|
|
# define MAXSYMLINKS 20
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
|
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
|
#endif
|
|
|
|
/* Define this independently so that stdint.h is not a prerequisite. */
|
|
#ifndef SIZE_MAX
|
|
# define SIZE_MAX ((size_t) -1)
|
|
#endif
|
|
|
|
#if !FUNC_REALPATH_WORKS || defined _LIBC
|
|
|
|
static void
|
|
alloc_failed (void)
|
|
{
|
|
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
|
/* Avoid errno problem without using the malloc or realloc modules; see:
|
|
http://lists.gnu.org/archive/html/bug-gnulib/2016-08/msg00025.html */
|
|
errno = ENOMEM;
|
|
#endif
|
|
}
|
|
|
|
/* Return the canonical absolute name of file NAME. A canonical name
|
|
does not contain any ".", ".." components nor any repeated path
|
|
separators ('/') or symlinks. All path components must exist. If
|
|
RESOLVED is null, the result is malloc'd; otherwise, if the
|
|
canonical name is PATH_MAX chars or more, returns null with 'errno'
|
|
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
|
|
returns the name in RESOLVED. If the name cannot be resolved and
|
|
RESOLVED is non-NULL, it contains the path of the first component
|
|
that cannot be resolved. If the path can be resolved, RESOLVED
|
|
holds the same value as the value returned. */
|
|
|
|
char *
|
|
__realpath (const char *name, char *resolved)
|
|
{
|
|
char *rpath, *dest, *extra_buf = NULL;
|
|
const char *start, *end, *rpath_limit;
|
|
long int path_max;
|
|
int num_links = 0;
|
|
size_t prefix_len;
|
|
|
|
if (name == NULL)
|
|
{
|
|
/* As per Single Unix Specification V2 we must return an error if
|
|
either parameter is a null pointer. We extend this to allow
|
|
the RESOLVED parameter to be NULL in case the we are expected to
|
|
allocate the room for the return value. */
|
|
__set_errno (EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
if (name[0] == '\0')
|
|
{
|
|
/* As per Single Unix Specification V2 we must return an error if
|
|
the name argument points to an empty string. */
|
|
__set_errno (ENOENT);
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef PATH_MAX
|
|
path_max = PATH_MAX;
|
|
#else
|
|
path_max = pathconf (name, _PC_PATH_MAX);
|
|
if (path_max <= 0)
|
|
path_max = 8192;
|
|
#endif
|
|
|
|
if (resolved == NULL)
|
|
{
|
|
rpath = malloc (path_max);
|
|
if (rpath == NULL)
|
|
{
|
|
alloc_failed ();
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
rpath = resolved;
|
|
rpath_limit = rpath + path_max;
|
|
|
|
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
|
|
and MS-DOS X:/foo/bar file names. */
|
|
prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
|
|
|
if (!IS_ABSOLUTE_FILE_NAME (name))
|
|
{
|
|
if (!__getcwd (rpath, path_max))
|
|
{
|
|
rpath[0] = '\0';
|
|
goto error;
|
|
}
|
|
dest = strchr (rpath, '\0');
|
|
start = name;
|
|
prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
|
|
}
|
|
else
|
|
{
|
|
dest = rpath;
|
|
if (prefix_len)
|
|
{
|
|
memcpy (rpath, name, prefix_len);
|
|
dest += prefix_len;
|
|
}
|
|
*dest++ = '/';
|
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
|
{
|
|
if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
|
|
*dest++ = '/';
|
|
*dest = '\0';
|
|
}
|
|
start = name + prefix_len;
|
|
}
|
|
|
|
for (end = start; *start; start = end)
|
|
{
|
|
#ifdef _LIBC
|
|
struct stat64 st;
|
|
#else
|
|
struct stat st;
|
|
#endif
|
|
|
|
/* Skip sequence of multiple path-separators. */
|
|
while (ISSLASH (*start))
|
|
++start;
|
|
|
|
/* Find end of path component. */
|
|
for (end = start; *end && !ISSLASH (*end); ++end)
|
|
/* Nothing. */;
|
|
|
|
if (end - start == 0)
|
|
break;
|
|
else if (end - start == 1 && start[0] == '.')
|
|
/* nothing */;
|
|
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
|
|
{
|
|
/* Back up to previous component, ignore if at root already. */
|
|
if (dest > rpath + prefix_len + 1)
|
|
for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
|
|
continue;
|
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
|
|
&& dest == rpath + 1 && !prefix_len
|
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
|
dest++;
|
|
}
|
|
else
|
|
{
|
|
size_t new_size;
|
|
|
|
if (!ISSLASH (dest[-1]))
|
|
*dest++ = '/';
|
|
|
|
if (dest + (end - start) >= rpath_limit)
|
|
{
|
|
ptrdiff_t dest_offset = dest - rpath;
|
|
char *new_rpath;
|
|
|
|
if (resolved)
|
|
{
|
|
__set_errno (ENAMETOOLONG);
|
|
if (dest > rpath + prefix_len + 1)
|
|
dest--;
|
|
*dest = '\0';
|
|
goto error;
|
|
}
|
|
new_size = rpath_limit - rpath;
|
|
if (end - start + 1 > path_max)
|
|
new_size += end - start + 1;
|
|
else
|
|
new_size += path_max;
|
|
new_rpath = (char *) realloc (rpath, new_size);
|
|
if (new_rpath == NULL)
|
|
{
|
|
alloc_failed ();
|
|
goto error;
|
|
}
|
|
rpath = new_rpath;
|
|
rpath_limit = rpath + new_size;
|
|
|
|
dest = rpath + dest_offset;
|
|
}
|
|
|
|
#ifdef _LIBC
|
|
dest = __mempcpy (dest, start, end - start);
|
|
#else
|
|
memcpy (dest, start, end - start);
|
|
dest += end - start;
|
|
#endif
|
|
*dest = '\0';
|
|
|
|
#ifdef _LIBC
|
|
if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
|
|
#else
|
|
if (lstat (rpath, &st) < 0)
|
|
#endif
|
|
goto error;
|
|
|
|
if (S_ISLNK (st.st_mode))
|
|
{
|
|
char *buf;
|
|
size_t len;
|
|
ssize_t n;
|
|
|
|
if (++num_links > MAXSYMLINKS)
|
|
{
|
|
__set_errno (ELOOP);
|
|
goto error;
|
|
}
|
|
|
|
buf = malloca (path_max);
|
|
if (!buf)
|
|
{
|
|
__set_errno (ENOMEM);
|
|
goto error;
|
|
}
|
|
|
|
n = __readlink (rpath, buf, path_max - 1);
|
|
if (n < 0)
|
|
{
|
|
int saved_errno = errno;
|
|
freea (buf);
|
|
__set_errno (saved_errno);
|
|
goto error;
|
|
}
|
|
buf[n] = '\0';
|
|
|
|
if (!extra_buf)
|
|
{
|
|
extra_buf = malloca (path_max);
|
|
if (!extra_buf)
|
|
{
|
|
freea (buf);
|
|
__set_errno (ENOMEM);
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
len = strlen (end);
|
|
/* Check that n + len + 1 doesn't overflow and is <= path_max. */
|
|
if (n >= SIZE_MAX - len || n + len >= path_max)
|
|
{
|
|
freea (buf);
|
|
__set_errno (ENAMETOOLONG);
|
|
goto error;
|
|
}
|
|
|
|
/* Careful here, end may be a pointer into extra_buf... */
|
|
memmove (&extra_buf[n], end, len + 1);
|
|
name = end = memcpy (extra_buf, buf, n);
|
|
|
|
if (IS_ABSOLUTE_FILE_NAME (buf))
|
|
{
|
|
size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
|
|
|
|
if (pfxlen)
|
|
memcpy (rpath, buf, pfxlen);
|
|
dest = rpath + pfxlen;
|
|
*dest++ = '/'; /* It's an absolute symlink */
|
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
|
|
{
|
|
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
|
|
*dest++ = '/';
|
|
*dest = '\0';
|
|
}
|
|
/* Install the new prefix to be in effect hereafter. */
|
|
prefix_len = pfxlen;
|
|
}
|
|
else
|
|
{
|
|
/* Back up to previous component, ignore if at root
|
|
already: */
|
|
if (dest > rpath + prefix_len + 1)
|
|
for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
|
|
continue;
|
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
|
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
|
|
dest++;
|
|
}
|
|
}
|
|
else if (!S_ISDIR (st.st_mode) && *end != '\0')
|
|
{
|
|
__set_errno (ENOTDIR);
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
|
|
--dest;
|
|
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
|
|
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
|
|
dest++;
|
|
*dest = '\0';
|
|
|
|
if (extra_buf)
|
|
freea (extra_buf);
|
|
|
|
return rpath;
|
|
|
|
error:
|
|
{
|
|
int saved_errno = errno;
|
|
if (extra_buf)
|
|
freea (extra_buf);
|
|
if (resolved == NULL)
|
|
free (rpath);
|
|
__set_errno (saved_errno);
|
|
}
|
|
return NULL;
|
|
}
|
|
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
|
|
#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
|
|
|
|
|
|
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
|
|
char *
|
|
attribute_compat_text_section
|
|
__old_realpath (const char *name, char *resolved)
|
|
{
|
|
if (resolved == NULL)
|
|
{
|
|
__set_errno (EINVAL);
|
|
return NULL;
|
|
}
|
|
|
|
return __realpath (name, resolved);
|
|
}
|
|
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
|
|
#endif
|
|
|
|
|
|
char *
|
|
__canonicalize_file_name (const char *name)
|
|
{
|
|
return __realpath (name, NULL);
|
|
}
|
|
weak_alias (__canonicalize_file_name, canonicalize_file_name)
|
|
|
|
#else
|
|
|
|
/* This declaration is solely to ensure that after preprocessing
|
|
this file is never empty. */
|
|
typedef int dummy;
|
|
|
|
#endif
|