(root)/
tar-1.35/
gnu/
canonicalize-lgpl.c
       1  /* Return the canonical absolute name of a given file.
       2     Copyright (C) 1996-2023 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 <string.h>
      34  #include <sys/stat.h>
      35  #include <unistd.h>
      36  
      37  #include <eloop-threshold.h>
      38  #include <filename.h>
      39  #include <idx.h>
      40  #include <intprops.h>
      41  #include <scratch_buffer.h>
      42  
      43  #ifdef _LIBC
      44  # include <shlib-compat.h>
      45  # define GCC_LINT 1
      46  # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
      47  #else
      48  # define __canonicalize_file_name canonicalize_file_name
      49  # define __realpath realpath
      50  # define __strdup strdup
      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  /* Scratch buffers used by realpath_stk and managed by __realpath.  */
     184  struct realpath_bufs
     185  {
     186    struct scratch_buffer rname;
     187    struct scratch_buffer extra;
     188    struct scratch_buffer link;
     189  };
     190  
     191  static char *
     192  realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs)
     193  {
     194    char *dest;
     195    char const *start;
     196    char const *end;
     197    int num_links = 0;
     198  
     199    if (name == NULL)
     200      {
     201        /* As per Single Unix Specification V2 we must return an error if
     202           either parameter is a null pointer.  We extend this to allow
     203           the RESOLVED parameter to be NULL in case the we are expected to
     204           allocate the room for the return value.  */
     205        __set_errno (EINVAL);
     206        return NULL;
     207      }
     208  
     209    if (name[0] == '\0')
     210      {
     211        /* As per Single Unix Specification V2 we must return an error if
     212           the name argument points to an empty string.  */
     213        __set_errno (ENOENT);
     214        return NULL;
     215      }
     216  
     217    char *rname = bufs->rname.data;
     218    bool end_in_extra_buffer = false;
     219    bool failed = true;
     220  
     221    /* This is always zero for Posix hosts, but can be 2 for MS-Windows
     222       and MS-DOS X:/foo/bar file names.  */
     223    idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
     224  
     225    if (!IS_ABSOLUTE_FILE_NAME (name))
     226      {
     227        while (!__getcwd (bufs->rname.data, bufs->rname.length))
     228          {
     229            if (errno != ERANGE)
     230              {
     231                dest = rname;
     232                goto error;
     233              }
     234            if (!scratch_buffer_grow (&bufs->rname))
     235              return NULL;
     236            rname = bufs->rname.data;
     237          }
     238        dest = __rawmemchr (rname, '\0');
     239        start = name;
     240        prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
     241      }
     242    else
     243      {
     244        dest = __mempcpy (rname, name, prefix_len);
     245        *dest++ = '/';
     246        if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
     247          {
     248            if (prefix_len == 0 /* implies ISSLASH (name[0]) */
     249                && ISSLASH (name[1]) && !ISSLASH (name[2]))
     250              *dest++ = '/';
     251            *dest = '\0';
     252          }
     253        start = name + prefix_len;
     254      }
     255  
     256    for ( ; *start; start = end)
     257      {
     258        /* Skip sequence of multiple file name separators.  */
     259        while (ISSLASH (*start))
     260          ++start;
     261  
     262        /* Find end of component.  */
     263        for (end = start; *end && !ISSLASH (*end); ++end)
     264          /* Nothing.  */;
     265  
     266        /* Length of this file name component; it can be zero if a file
     267           name ends in '/'.  */
     268        idx_t startlen = end - start;
     269  
     270        if (startlen == 0)
     271          break;
     272        else if (startlen == 1 && start[0] == '.')
     273          /* nothing */;
     274        else if (startlen == 2 && start[0] == '.' && start[1] == '.')
     275          {
     276            /* Back up to previous component, ignore if at root already.  */
     277            if (dest > rname + prefix_len + 1)
     278              for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
     279                continue;
     280            if (DOUBLE_SLASH_IS_DISTINCT_ROOT
     281                && dest == rname + 1 && !prefix_len
     282                && ISSLASH (*dest) && !ISSLASH (dest[1]))
     283              dest++;
     284          }
     285        else
     286          {
     287            if (!ISSLASH (dest[-1]))
     288              *dest++ = '/';
     289  
     290            while (rname + bufs->rname.length - dest
     291                   < startlen + sizeof dir_suffix)
     292              {
     293                idx_t dest_offset = dest - rname;
     294                if (!scratch_buffer_grow_preserve (&bufs->rname))
     295                  return NULL;
     296                rname = bufs->rname.data;
     297                dest = rname + dest_offset;
     298              }
     299  
     300            dest = __mempcpy (dest, start, startlen);
     301            *dest = '\0';
     302  
     303            char *buf;
     304            ssize_t n;
     305            while (true)
     306              {
     307                buf = bufs->link.data;
     308                idx_t bufsize = bufs->link.length;
     309                n = __readlink (rname, buf, bufsize - 1);
     310                if (n < bufsize - 1)
     311                  break;
     312                if (!scratch_buffer_grow (&bufs->link))
     313                  return NULL;
     314              }
     315            if (0 <= n)
     316              {
     317                if (++num_links > __eloop_threshold ())
     318                  {
     319                    __set_errno (ELOOP);
     320                    goto error;
     321                  }
     322  
     323                buf[n] = '\0';
     324  
     325                char *extra_buf = bufs->extra.data;
     326                idx_t end_idx IF_LINT (= 0);
     327                if (end_in_extra_buffer)
     328                  end_idx = end - extra_buf;
     329                size_t len = strlen (end);
     330                if (INT_ADD_OVERFLOW (len, n))
     331                  {
     332                    __set_errno (ENOMEM);
     333                    return NULL;
     334                  }
     335                while (bufs->extra.length <= len + n)
     336                  {
     337                    if (!scratch_buffer_grow_preserve (&bufs->extra))
     338                      return NULL;
     339                    extra_buf = bufs->extra.data;
     340                  }
     341                if (end_in_extra_buffer)
     342                  end = extra_buf + end_idx;
     343  
     344                /* Careful here, end may be a pointer into extra_buf... */
     345                memmove (&extra_buf[n], end, len + 1);
     346                name = end = memcpy (extra_buf, buf, n);
     347                end_in_extra_buffer = true;
     348  
     349                if (IS_ABSOLUTE_FILE_NAME (buf))
     350                  {
     351                    idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
     352  
     353                    dest = __mempcpy (rname, buf, pfxlen);
     354                    *dest++ = '/'; /* It's an absolute symlink */
     355                    if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
     356                      {
     357                        if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
     358                          *dest++ = '/';
     359                        *dest = '\0';
     360                      }
     361                    /* Install the new prefix to be in effect hereafter.  */
     362                    prefix_len = pfxlen;
     363                  }
     364                else
     365                  {
     366                    /* Back up to previous component, ignore if at root
     367                       already: */
     368                    if (dest > rname + prefix_len + 1)
     369                      for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
     370                        continue;
     371                    if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
     372                        && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
     373                      dest++;
     374                  }
     375              }
     376            else if (! (suffix_requires_dir_check (end)
     377                        ? dir_check (rname, dest)
     378                        : errno == EINVAL))
     379              goto error;
     380          }
     381      }
     382    if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
     383      --dest;
     384    if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
     385        && ISSLASH (*dest) && !ISSLASH (dest[1]))
     386      dest++;
     387    failed = false;
     388  
     389  error:
     390    *dest++ = '\0';
     391    if (resolved != NULL)
     392      {
     393        /* Copy the full result on success or partial result if failure was due
     394           to the path not existing or not being accessible.  */
     395        if ((!failed || errno == ENOENT || errno == EACCES)
     396            && dest - rname <= get_path_max ())
     397          {
     398            strcpy (resolved, rname);
     399            if (failed)
     400              return NULL;
     401            else
     402              return resolved;
     403          }
     404        if (!failed)
     405          __set_errno (ENAMETOOLONG);
     406        return NULL;
     407      }
     408    else
     409      {
     410        if (failed)
     411          return NULL;
     412        else
     413          return __strdup (bufs->rname.data);
     414      }
     415  }
     416  
     417  /* Return the canonical absolute name of file NAME.  A canonical name
     418     does not contain any ".", ".." components nor any repeated file name
     419     separators ('/') or symlinks.  All file name components must exist.  If
     420     RESOLVED is null, the result is malloc'd; otherwise, if the
     421     canonical name is PATH_MAX chars or more, returns null with 'errno'
     422     set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
     423     returns the name in RESOLVED.  If the name cannot be resolved and
     424     RESOLVED is non-NULL, it contains the name of the first component
     425     that cannot be resolved.  If the name can be resolved, RESOLVED
     426     holds the same value as the value returned.  */
     427  
     428  char *
     429  __realpath (const char *name, char *resolved)
     430  {
     431    struct realpath_bufs bufs;
     432    scratch_buffer_init (&bufs.rname);
     433    scratch_buffer_init (&bufs.extra);
     434    scratch_buffer_init (&bufs.link);
     435    char *result = realpath_stk (name, resolved, &bufs);
     436    scratch_buffer_free (&bufs.link);
     437    scratch_buffer_free (&bufs.extra);
     438    scratch_buffer_free (&bufs.rname);
     439    return result;
     440  }
     441  libc_hidden_def (__realpath)
     442  versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
     443  
     444  #endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
     445  
     446  
     447  #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
     448  char *
     449  attribute_compat_text_section
     450  __old_realpath (const char *name, char *resolved)
     451  {
     452    if (resolved == NULL)
     453      {
     454        __set_errno (EINVAL);
     455        return NULL;
     456      }
     457  
     458    return __realpath (name, resolved);
     459  }
     460  compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
     461  #endif
     462  
     463  
     464  char *
     465  __canonicalize_file_name (const char *name)
     466  {
     467    return __realpath (name, NULL);
     468  }
     469  weak_alias (__canonicalize_file_name, canonicalize_file_name)