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