Diff for /embedaddon/libiconv/srclib/canonicalize-lgpl.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/05/29 09:29:43 version 1.1.1.3, 2021/03/17 13:38:46
Line 1 Line 1
 /* Return the canonical absolute name of a given file.  /* Return the canonical absolute name of a given file.
   Copyright (C) 1996-2011 Free Software Foundation, Inc.   Copyright (C) 1996-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.     This file is part of the GNU C Library.
   
    This program is free software: you can redistribute it and/or modify     This program is free software: you can redistribute it and/or modify
Line 13 Line 13
    GNU General Public License for more details.     GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
   
 #ifndef _LIBC  #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  # define _GL_USE_STDLIB_ALLOC 1
 # include <config.h>  # include <config.h>
 #endif  #endif
   
 #if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC  #if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
   
 /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc  
    optimizes away the name == NULL test below.  */  
 #define _GL_ARG_NONNULL(params)  
   
 /* Specification.  */  /* Specification.  */
 #include <stdlib.h>  #include <stdlib.h>
   
Line 51 Line 51
 # define __realpath realpath  # define __realpath realpath
 # include "pathmax.h"  # include "pathmax.h"
 # include "malloca.h"  # include "malloca.h"
   # include "dosname.h"
 # if HAVE_GETCWD  # if HAVE_GETCWD
 #  if IN_RELOCWRAPPER  #  if IN_RELOCWRAPPER
     /* When building the relocatable program wrapper, use the system's getcwd      /* When building the relocatable program wrapper, use the system's getcwd
Line 58 Line 59
      */       */
 #   undef getcwd  #   undef getcwd
 #  endif  #  endif
#  ifdef VMS#  if defined VMS && !defined getcwd
    /* We want the directory in Unix syntax, not in VMS syntax.  */    /* We want the directory in Unix syntax, not in VMS syntax.
        The gnulib override of 'getcwd' takes 2 arguments; the original VMS
        'getcwd' takes 3 arguments.  */
 #   define __getcwd(buf, max) getcwd (buf, max, 0)  #   define __getcwd(buf, max) getcwd (buf, max, 0)
 #  else  #  else
 #   define __getcwd getcwd  #   define __getcwd getcwd
Line 82 Line 85
 # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0  # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
 #endif  #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  #if !FUNC_REALPATH_WORKS || defined _LIBC
   
   static void
   alloc_failed (void)
   {
   #if defined _WIN32 && ! defined __CYGWIN__
     /* Avoid errno problem without using the malloc or realloc modules; see:
        https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html  */
     errno = ENOMEM;
   #endif
   }
   
 /* Return the canonical absolute name of file NAME.  A canonical name  /* Return the canonical absolute name of file NAME.  A canonical name
   does not contain any `.', `..' components nor any repeated path   does not contain any ".", ".." components nor any repeated path
    separators ('/') or symlinks.  All path components must exist.  If     separators ('/') or symlinks.  All path components must exist.  If
    RESOLVED is null, the result is malloc'd; otherwise, if the     RESOLVED is null, the result is malloc'd; otherwise, if the
   canonical name is PATH_MAX chars or more, returns null with `errno'   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,     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     returns the name in RESOLVED.  If the name cannot be resolved and
    RESOLVED is non-NULL, it contains the path of the first component     RESOLVED is non-NULL, it contains the path of the first component
Line 101  __realpath (const char *name, char *resolved) Line 120  __realpath (const char *name, char *resolved)
   const char *start, *end, *rpath_limit;    const char *start, *end, *rpath_limit;
   long int path_max;    long int path_max;
   int num_links = 0;    int num_links = 0;
     size_t prefix_len;
   
   if (name == NULL)    if (name == NULL)
     {      {
Line 133  __realpath (const char *name, char *resolved) Line 153  __realpath (const char *name, char *resolved)
       rpath = malloc (path_max);        rpath = malloc (path_max);
       if (rpath == NULL)        if (rpath == NULL)
         {          {
          /* It's easier to set errno to ENOMEM than to rely on the          alloc_failed ();
             'malloc-posix' gnulib module.  */ 
          errno = ENOMEM; 
           return NULL;            return NULL;
         }          }
     }      }
Line 143  __realpath (const char *name, char *resolved) Line 161  __realpath (const char *name, char *resolved)
     rpath = resolved;      rpath = resolved;
   rpath_limit = rpath + path_max;    rpath_limit = rpath + path_max;
   
  if (name[0] != '/')  /* 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))        if (!__getcwd (rpath, path_max))
         {          {
Line 151  __realpath (const char *name, char *resolved) Line 173  __realpath (const char *name, char *resolved)
           goto error;            goto error;
         }          }
       dest = strchr (rpath, '\0');        dest = strchr (rpath, '\0');
         start = name;
         prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
     }      }
   else    else
     {      {
      rpath[0] = '/';      dest = rpath;
      dest = rpath + 1;      if (prefix_len)
      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')        {
        *dest++ = '/';          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 (start = end = name; *start; start = end)  for (end = start; *start; start = end)
     {      {
 #ifdef _LIBC  #ifdef _LIBC
       struct stat64 st;        struct stat64 st;
 #else  #else
       struct stat st;        struct stat st;
 #endif  #endif
       int n;  
   
       /* Skip sequence of multiple path-separators.  */        /* Skip sequence of multiple path-separators.  */
      while (*start == '/')      while (ISSLASH (*start))
         ++start;          ++start;
   
       /* Find end of path component.  */        /* Find end of path component.  */
      for (end = start; *end && *end != '/'; ++end)      for (end = start; *end && !ISSLASH (*end); ++end)
         /* Nothing.  */;          /* Nothing.  */;
   
       if (end - start == 0)        if (end - start == 0)
Line 184  __realpath (const char *name, char *resolved) Line 217  __realpath (const char *name, char *resolved)
       else if (end - start == 2 && start[0] == '.' && start[1] == '.')        else if (end - start == 2 && start[0] == '.' && start[1] == '.')
         {          {
           /* Back up to previous component, ignore if at root already.  */            /* Back up to previous component, ignore if at root already.  */
          if (dest > rpath + 1)          if (dest > rpath + prefix_len + 1)
            while ((--dest)[-1] != '/');            for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
          if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1              continue;
              && *dest == '/')          if (DOUBLE_SLASH_IS_DISTINCT_ROOT
               && dest == rpath + 1 && !prefix_len
               && ISSLASH (*dest) && !ISSLASH (dest[1]))
             dest++;              dest++;
         }          }
       else        else
         {          {
           size_t new_size;            size_t new_size;
   
          if (dest[-1] != '/')          if (!ISSLASH (dest[-1]))
             *dest++ = '/';              *dest++ = '/';
   
           if (dest + (end - start) >= rpath_limit)            if (dest + (end - start) >= rpath_limit)
Line 205  __realpath (const char *name, char *resolved) Line 240  __realpath (const char *name, char *resolved)
               if (resolved)                if (resolved)
                 {                  {
                   __set_errno (ENAMETOOLONG);                    __set_errno (ENAMETOOLONG);
                  if (dest > rpath + 1)                  if (dest > rpath + prefix_len + 1)
                     dest--;                      dest--;
                   *dest = '\0';                    *dest = '\0';
                   goto error;                    goto error;
Line 218  __realpath (const char *name, char *resolved) Line 253  __realpath (const char *name, char *resolved)
               new_rpath = (char *) realloc (rpath, new_size);                new_rpath = (char *) realloc (rpath, new_size);
               if (new_rpath == NULL)                if (new_rpath == NULL)
                 {                  {
                  /* It's easier to set errno to ENOMEM than to rely on the                  alloc_failed ();
                     'realloc-posix' gnulib module.  */ 
                  errno = ENOMEM; 
                   goto error;                    goto error;
                 }                  }
               rpath = new_rpath;                rpath = new_rpath;
Line 237  __realpath (const char *name, char *resolved) Line 270  __realpath (const char *name, char *resolved)
 #endif  #endif
           *dest = '\0';            *dest = '\0';
   
             /* FIXME: if lstat fails with errno == EOVERFLOW,
                the entry exists.  */
 #ifdef _LIBC  #ifdef _LIBC
           if (__lxstat64 (_STAT_VER, rpath, &st) < 0)            if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
 #else  #else
Line 248  __realpath (const char *name, char *resolved) Line 283  __realpath (const char *name, char *resolved)
             {              {
               char *buf;                char *buf;
               size_t len;                size_t len;
                 ssize_t n;
   
               if (++num_links > MAXSYMLINKS)                if (++num_links > MAXSYMLINKS)
                 {                  {
Line 258  __realpath (const char *name, char *resolved) Line 294  __realpath (const char *name, char *resolved)
               buf = malloca (path_max);                buf = malloca (path_max);
               if (!buf)                if (!buf)
                 {                  {
                  errno = ENOMEM;                  __set_errno (ENOMEM);
                   goto error;                    goto error;
                 }                  }
   
Line 267  __realpath (const char *name, char *resolved) Line 303  __realpath (const char *name, char *resolved)
                 {                  {
                   int saved_errno = errno;                    int saved_errno = errno;
                   freea (buf);                    freea (buf);
                  errno = saved_errno;                  __set_errno (saved_errno);
                   goto error;                    goto error;
                 }                  }
               buf[n] = '\0';                buf[n] = '\0';
Line 278  __realpath (const char *name, char *resolved) Line 314  __realpath (const char *name, char *resolved)
                   if (!extra_buf)                    if (!extra_buf)
                     {                      {
                       freea (buf);                        freea (buf);
                      errno = ENOMEM;                      __set_errno (ENOMEM);
                       goto error;                        goto error;
                     }                      }
                 }                  }
   
               len = strlen (end);                len = strlen (end);
              if ((long int) (n + len) >= path_max)              /* Check that n + len + 1 doesn't overflow and is <= path_max. */
               if (n >= SIZE_MAX - len || n + len >= path_max)
                 {                  {
                   freea (buf);                    freea (buf);
                   __set_errno (ENAMETOOLONG);                    __set_errno (ENAMETOOLONG);
Line 295  __realpath (const char *name, char *resolved) Line 332  __realpath (const char *name, char *resolved)
               memmove (&extra_buf[n], end, len + 1);                memmove (&extra_buf[n], end, len + 1);
               name = end = memcpy (extra_buf, buf, n);                name = end = memcpy (extra_buf, buf, n);
   
              if (buf[0] == '/')              if (IS_ABSOLUTE_FILE_NAME (buf))
                 {                  {
                  dest = rpath + 1;     /* It's an absolute symlink */                  size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
                    *dest++ = '/';                  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                else
                 {                  {
                   /* Back up to previous component, ignore if at root                    /* Back up to previous component, ignore if at root
                      already: */                       already: */
                  if (dest > rpath + 1)                  if (dest > rpath + prefix_len + 1)
                    while ((--dest)[-1] != '/');                    for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
                       continue;
                   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1                    if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
                      && *dest == '/')                      && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
                     dest++;                      dest++;
                 }                  }
             }              }
Line 319  __realpath (const char *name, char *resolved) Line 368  __realpath (const char *name, char *resolved)
             }              }
         }          }
     }      }
  if (dest > rpath + 1 && dest[-1] == '/')  if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
     --dest;      --dest;
  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
       && ISSLASH (*dest) && !ISSLASH (dest[1]))
     dest++;      dest++;
   *dest = '\0';    *dest = '\0';
   
Line 337  error: Line 387  error:
       freea (extra_buf);        freea (extra_buf);
     if (resolved == NULL)      if (resolved == NULL)
       free (rpath);        free (rpath);
    errno = saved_errno;    __set_errno (saved_errno);
   }    }
   return NULL;    return NULL;
 }  }

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>