(root)/
bison-3.8.2/
lib/
canonicalize-lgpl.c
       1  /* Return the canonical absolute name of a given file.
       2     Copyright (C) 1996-2021 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _LIBC
      20  /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
      21     optimizes away the name == NULL test below.  */
      22  # define _GL_ARG_NONNULL(params)
      23  
      24  # include <libc-config.h>
      25  #endif
      26  
      27  /* Specification.  */
      28  #include <stdlib.h>
      29  
      30  #include <errno.h>
      31  #include <fcntl.h>
      32  #include <limits.h>
      33  #include <stdbool.h>
      34  #include <string.h>
      35  #include <sys/stat.h>
      36  #include <unistd.h>
      37  
      38  #include <eloop-threshold.h>
      39  #include <filename.h>
      40  #include <idx.h>
      41  #include <intprops.h>
      42  #include <scratch_buffer.h>
      43  
      44  #ifdef _LIBC
      45  # include <shlib-compat.h>
      46  # define GCC_LINT 1
      47  # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
      48  #else
      49  # define __canonicalize_file_name canonicalize_file_name
      50  # define __realpath realpath
      51  # include "pathmax.h"
      52  # define __faccessat faccessat
      53  # if defined _WIN32 && !defined __CYGWIN__
      54  #  define __getcwd _getcwd
      55  # elif HAVE_GETCWD
      56  #  if IN_RELOCWRAPPER
      57      /* When building the relocatable program wrapper, use the system's getcwd
      58         function, not the gnulib override, otherwise we would get a link error.
      59       */
      60  #   undef getcwd
      61  #  endif
      62  #  if defined VMS && !defined getcwd
      63      /* We want the directory in Unix syntax, not in VMS syntax.
      64         The gnulib override of 'getcwd' takes 2 arguments; the original VMS
      65         'getcwd' takes 3 arguments.  */
      66  #   define __getcwd(buf, max) getcwd (buf, max, 0)
      67  #  else
      68  #   define __getcwd getcwd
      69  #  endif
      70  # else
      71  #  define __getcwd(buf, max) getwd (buf)
      72  # endif
      73  # define __mempcpy mempcpy
      74  # define __pathconf pathconf
      75  # define __rawmemchr rawmemchr
      76  # define __readlink readlink
      77  # if IN_RELOCWRAPPER
      78      /* When building the relocatable program wrapper, use the system's memmove
      79         function, not the gnulib override, otherwise we would get a link error.
      80       */
      81  #  undef memmove
      82  # endif
      83  #endif
      84  
      85  /* Suppress bogus GCC -Wmaybe-uninitialized warnings.  */
      86  #if defined GCC_LINT || defined lint
      87  # define IF_LINT(Code) Code
      88  #else
      89  # define IF_LINT(Code) /* empty */
      90  #endif
      91  
      92  #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
      93  # define DOUBLE_SLASH_IS_DISTINCT_ROOT false
      94  #endif
      95  
      96  #if defined _LIBC || !FUNC_REALPATH_WORKS
      97  
      98  /* Return true if FILE's existence can be shown, false (setting errno)
      99     otherwise.  Follow symbolic links.  */
     100  static bool
     101  file_accessible (char const *file)
     102  {
     103  # if defined _LIBC || HAVE_FACCESSAT
     104    return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
     105  # else
     106    struct stat st;
     107    return stat (file, &st) == 0 || errno == EOVERFLOW;
     108  # endif
     109  }
     110  
     111  /* True if concatenating END as a suffix to a file name means that the
     112     code needs to check that the file name is that of a searchable
     113     directory, since the canonicalize_filename_mode_stk code won't
     114     check this later anyway when it checks an ordinary file name
     115     component within END.  END must either be empty, or start with a
     116     slash.  */
     117  
     118  static bool _GL_ATTRIBUTE_PURE
     119  suffix_requires_dir_check (char const *end)
     120  {
     121    /* If END does not start with a slash, the suffix is OK.  */
     122    while (ISSLASH (*end))
     123      {
     124        /* Two or more slashes act like a single slash.  */
     125        do
     126          end++;
     127        while (ISSLASH (*end));
     128  
     129        switch (*end++)
     130          {
     131          default: return false;  /* An ordinary file name component is OK.  */
     132          case '\0': return true; /* Trailing "/" is trouble.  */
     133          case '.': break;        /* Possibly "." or "..".  */
     134          }
     135        /* Trailing "/.", or "/.." even if not trailing, is trouble.  */
     136        if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
     137          return true;
     138      }
     139  
     140    return false;
     141  }
     142  
     143  /* Append this to a file name to test whether it is a searchable directory.
     144     On POSIX platforms "/" suffices, but "/./" is sometimes needed on
     145     macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
     146     platforms like AIX 7.2 that need at least "/.".  */
     147  
     148  # if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
     149  static char const dir_suffix[] = "/";
     150  # else
     151  static char const dir_suffix[] = "/./";
     152  # endif
     153  
     154  /* Return true if DIR is a searchable dir, false (setting errno) otherwise.
     155     DIREND points to the NUL byte at the end of the DIR string.
     156     Store garbage into DIREND[0 .. strlen (dir_suffix)].  */
     157  
     158  static bool
     159  dir_check (char *dir, char *dirend)
     160  {
     161    strcpy (dirend, dir_suffix);
     162    return file_accessible (dir);
     163  }
     164  
     165  static idx_t
     166  get_path_max (void)
     167  {
     168  # ifdef PATH_MAX
     169    long int path_max = PATH_MAX;
     170  # else
     171    /* The caller invoked realpath with a null RESOLVED, even though
     172       PATH_MAX is not defined as a constant.  The glibc manual says
     173       programs should not do this, and POSIX says the behavior is undefined.
     174       Historically, glibc here used the result of pathconf, or 1024 if that
     175       failed; stay consistent with this (dubious) historical practice.  */
     176    int err = errno;
     177    long int path_max = __pathconf ("/", _PC_PATH_MAX);
     178    __set_errno (err);
     179  # endif
     180    return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
     181  }
     182  
     183  /* Act like __realpath (see below), with an additional argument
     184     rname_buf that can be used as temporary storage.
     185  
     186     If GCC_LINT is defined, do not inline this function with GCC 10.1
     187     and later, to avoid creating a pointer to the stack that GCC
     188     -Wreturn-local-addr incorrectly complains about.  See:
     189     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
     190     Although the noinline attribute can hurt performance a bit, no better way
     191     to pacify GCC is known; even an explicit #pragma does not pacify GCC.
     192     When the GCC bug is fixed this workaround should be limited to the
     193     broken GCC versions.  */
     194  # if __GNUC_PREREQ (10, 1)
     195  #  if defined GCC_LINT || defined lint
     196  __attribute__ ((__noinline__))
     197  #  elif __OPTIMIZE__ && !__NO_INLINE__
     198  #   define GCC_BOGUS_WRETURN_LOCAL_ADDR
     199  #  endif
     200  # endif
     201  static char *
     202  realpath_stk (const char *name, char *resolved,
     203                struct scratch_buffer *rname_buf)
     204  {
     205    char *dest;
     206    char const *start;
     207    char const *end;
     208    int num_links = 0;
     209  
     210    if (name == NULL)
     211      {
     212        /* As per Single Unix Specification V2 we must return an error if
     213           either parameter is a null pointer.  We extend this to allow
     214           the RESOLVED parameter to be NULL in case the we are expected to
     215           allocate the room for the return value.  */
     216        __set_errno (EINVAL);
     217        return NULL;
     218      }
     219  
     220    if (name[0] == '\0')
     221      {
     222        /* As per Single Unix Specification V2 we must return an error if
     223           the name argument points to an empty string.  */
     224        __set_errno (ENOENT);
     225        return NULL;
     226      }
     227  
     228    struct scratch_buffer extra_buffer, link_buffer;
     229    scratch_buffer_init (&extra_buffer);
     230    scratch_buffer_init (&link_buffer);
     231    scratch_buffer_init (rname_buf);
     232    char *rname_on_stack = rname_buf->data;
     233    char *rname = rname_on_stack;
     234    bool end_in_extra_buffer = false;
     235    bool failed = true;
     236  
     237    /* This is always zero for Posix hosts, but can be 2 for MS-Windows
     238       and MS-DOS X:/foo/bar file names.  */
     239    idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
     240  
     241    if (!IS_ABSOLUTE_FILE_NAME (name))
     242      {
     243        while (!__getcwd (rname, rname_buf->length))
     244          {
     245            if (errno != ERANGE)
     246              {
     247                dest = rname;
     248                goto error;
     249              }
     250            if (!scratch_buffer_grow (rname_buf))
     251              goto error_nomem;
     252            rname = rname_buf->data;
     253          }
     254        dest = __rawmemchr (rname, '\0');
     255        start = name;
     256        prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
     257      }
     258    else
     259      {
     260        dest = __mempcpy (rname, name, prefix_len);
     261        *dest++ = '/';
     262        if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
     263          {
     264            if (prefix_len == 0 /* implies ISSLASH (name[0]) */
     265                && ISSLASH (name[1]) && !ISSLASH (name[2]))
     266              *dest++ = '/';
     267            *dest = '\0';
     268          }
     269        start = name + prefix_len;
     270      }
     271  
     272    for ( ; *start; start = end)
     273      {
     274        /* Skip sequence of multiple file name separators.  */
     275        while (ISSLASH (*start))
     276          ++start;
     277  
     278        /* Find end of component.  */
     279        for (end = start; *end && !ISSLASH (*end); ++end)
     280          /* Nothing.  */;
     281  
     282        /* Length of this file name component; it can be zero if a file
     283           name ends in '/'.  */
     284        idx_t startlen = end - start;
     285  
     286        if (startlen == 0)
     287          break;
     288        else if (startlen == 1 && start[0] == '.')
     289          /* nothing */;
     290        else if (startlen == 2 && start[0] == '.' && start[1] == '.')
     291          {
     292            /* Back up to previous component, ignore if at root already.  */
     293            if (dest > rname + prefix_len + 1)
     294              for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
     295                continue;
     296            if (DOUBLE_SLASH_IS_DISTINCT_ROOT
     297                && dest == rname + 1 && !prefix_len
     298                && ISSLASH (*dest) && !ISSLASH (dest[1]))
     299              dest++;
     300          }
     301        else
     302          {
     303            if (!ISSLASH (dest[-1]))
     304              *dest++ = '/';
     305  
     306            while (rname + rname_buf->length - dest
     307                   < startlen + sizeof dir_suffix)
     308              {
     309                idx_t dest_offset = dest - rname;
     310                if (!scratch_buffer_grow_preserve (rname_buf))
     311                  goto error_nomem;
     312                rname = rname_buf->data;
     313                dest = rname + dest_offset;
     314              }
     315  
     316            dest = __mempcpy (dest, start, startlen);
     317            *dest = '\0';
     318  
     319            char *buf;
     320            ssize_t n;
     321            while (true)
     322              {
     323                buf = link_buffer.data;
     324                idx_t bufsize = link_buffer.length;
     325                n = __readlink (rname, buf, bufsize - 1);
     326                if (n < bufsize - 1)
     327                  break;
     328                if (!scratch_buffer_grow (&link_buffer))
     329                  goto error_nomem;
     330              }
     331            if (0 <= n)
     332              {
     333                if (++num_links > __eloop_threshold ())
     334                  {
     335                    __set_errno (ELOOP);
     336                    goto error;
     337                  }
     338  
     339                buf[n] = '\0';
     340  
     341                char *extra_buf = extra_buffer.data;
     342                idx_t end_idx IF_LINT (= 0);
     343                if (end_in_extra_buffer)
     344                  end_idx = end - extra_buf;
     345                size_t len = strlen (end);
     346                if (INT_ADD_OVERFLOW (len, n))
     347                  {
     348                    __set_errno (ENOMEM);
     349                    goto error_nomem;
     350                  }
     351                while (extra_buffer.length <= len + n)
     352                  {
     353                    if (!scratch_buffer_grow_preserve (&extra_buffer))
     354                      goto error_nomem;
     355                    extra_buf = extra_buffer.data;
     356                  }
     357                if (end_in_extra_buffer)
     358                  end = extra_buf + end_idx;
     359  
     360                /* Careful here, end may be a pointer into extra_buf... */
     361                memmove (&extra_buf[n], end, len + 1);
     362                name = end = memcpy (extra_buf, buf, n);
     363                end_in_extra_buffer = true;
     364  
     365                if (IS_ABSOLUTE_FILE_NAME (buf))
     366                  {
     367                    idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
     368  
     369                    dest = __mempcpy (rname, buf, pfxlen);
     370                    *dest++ = '/'; /* It's an absolute symlink */
     371                    if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
     372                      {
     373                        if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
     374                          *dest++ = '/';
     375                        *dest = '\0';
     376                      }
     377                    /* Install the new prefix to be in effect hereafter.  */
     378                    prefix_len = pfxlen;
     379                  }
     380                else
     381                  {
     382                    /* Back up to previous component, ignore if at root
     383                       already: */
     384                    if (dest > rname + prefix_len + 1)
     385                      for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
     386                        continue;
     387                    if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
     388                        && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
     389                      dest++;
     390                  }
     391              }
     392            else if (! (suffix_requires_dir_check (end)
     393                        ? dir_check (rname, dest)
     394                        : errno == EINVAL))
     395              goto error;
     396          }
     397      }
     398    if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
     399      --dest;
     400    if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
     401        && ISSLASH (*dest) && !ISSLASH (dest[1]))
     402      dest++;
     403    failed = false;
     404  
     405  error:
     406    *dest++ = '\0';
     407    if (resolved != NULL && dest - rname <= get_path_max ())
     408      rname = strcpy (resolved, rname);
     409  
     410  error_nomem:
     411    scratch_buffer_free (&extra_buffer);
     412    scratch_buffer_free (&link_buffer);
     413  
     414    if (failed || rname == resolved)
     415      {
     416        scratch_buffer_free (rname_buf);
     417        return failed ? NULL : resolved;
     418      }
     419  
     420    return scratch_buffer_dupfree (rname_buf, dest - rname);
     421  }
     422  
     423  /* Return the canonical absolute name of file NAME.  A canonical name
     424     does not contain any ".", ".." components nor any repeated file name
     425     separators ('/') or symlinks.  All file name components must exist.  If
     426     RESOLVED is null, the result is malloc'd; otherwise, if the
     427     canonical name is PATH_MAX chars or more, returns null with 'errno'
     428     set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
     429     returns the name in RESOLVED.  If the name cannot be resolved and
     430     RESOLVED is non-NULL, it contains the name of the first component
     431     that cannot be resolved.  If the name can be resolved, RESOLVED
     432     holds the same value as the value returned.  */
     433  
     434  char *
     435  __realpath (const char *name, char *resolved)
     436  {
     437    #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
     438     #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
     439     #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
     440    #endif
     441    struct scratch_buffer rname_buffer;
     442    return realpath_stk (name, resolved, &rname_buffer);
     443  }
     444  libc_hidden_def (__realpath)
     445  versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
     446  
     447  #endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
     448  
     449  
     450  #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
     451  char *
     452  attribute_compat_text_section
     453  __old_realpath (const char *name, char *resolved)
     454  {
     455    if (resolved == NULL)
     456      {
     457        __set_errno (EINVAL);
     458        return NULL;
     459      }
     460  
     461    return __realpath (name, resolved);
     462  }
     463  compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
     464  #endif
     465  
     466  
     467  char *
     468  __canonicalize_file_name (const char *name)
     469  {
     470    return __realpath (name, NULL);
     471  }
     472  weak_alias (__canonicalize_file_name, canonicalize_file_name)