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

version 1.1.1.1, 2012/02/21 22:57:48 version 1.1.1.2, 2012/05/29 09:29:43
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-2003, 2005-2008 Free Software Foundation, Inc.   Copyright (C) 1996-2011 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 15 Line 15
    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 <http://www.gnu.org/licenses/>.  */
   
#include <config.h>#ifndef _LIBC
 # define _GL_USE_STDLIB_ALLOC 1
 # include <config.h>
 #endif
   
/* Avoid a clash of our rpl_realpath() function with the prototype in#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
   <stdlib.h> on Solaris 2.5.1.  */ 
#undef realpath 
   
#if !HAVE_CANONICALIZE_FILE_NAME || 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)
   
 #include <alloca.h>  
   
 /* Specification.  */  /* Specification.  */
 #include "canonicalize.h"  
   
 #include <stddef.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  
   
#if HAVE_UNISTD_H || defined _LIBC#include <alloca.h>
# include <unistd.h>#include <string.h>
#endif#include <unistd.h>
 
 #include <limits.h>  #include <limits.h>
   
 #if HAVE_SYS_PARAM_H || defined _LIBC  #if HAVE_SYS_PARAM_H || defined _LIBC
 # include <sys/param.h>  # include <sys/param.h>
 #endif  #endif
 #ifndef MAXSYMLINKS  
 # define MAXSYMLINKS 20  
 #endif  
   
 #include <sys/stat.h>  #include <sys/stat.h>
   
 #include <errno.h>  #include <errno.h>
#ifndef _LIBC#include <stddef.h>
# define __set_errno(e) errno = (e) 
# ifndef ENAMETOOLONG 
#  define ENAMETOOLONG EINVAL 
# endif 
#endif 
   
 #ifdef _LIBC  #ifdef _LIBC
 # include <shlib-compat.h>  # include <shlib-compat.h>
 #else  #else
 # define SHLIB_COMPAT(lib, introduced, obsoleted) 0  # define SHLIB_COMPAT(lib, introduced, obsoleted) 0
# define versioned_symbol(lib, local, symbol, version)# define versioned_symbol(lib, local, symbol, version) extern int dummy
 # define compat_symbol(lib, local, symbol, version)  # define compat_symbol(lib, local, symbol, version)
 # define weak_alias(local, symbol)  # define weak_alias(local, symbol)
 # define __canonicalize_file_name canonicalize_file_name  # define __canonicalize_file_name canonicalize_file_name
# define __realpath rpl_realpath# define __realpath realpath
 # include "pathmax.h"  # include "pathmax.h"
 # include "malloca.h"  # include "malloca.h"
 # if HAVE_GETCWD  # 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  #  ifdef VMS
     /* We want the directory in Unix syntax, not in VMS syntax.  */      /* We want the directory in Unix syntax, not in VMS syntax.  */
 #   define __getcwd(buf, max) getcwd (buf, max, 0)  #   define __getcwd(buf, max) getcwd (buf, max, 0)
Line 77 Line 68
 #  define __getcwd(buf, max) getwd (buf)  #  define __getcwd(buf, max) getwd (buf)
 # endif  # endif
 # define __readlink readlink  # define __readlink readlink
  /* On systems without symbolic links, call stat() instead of lstat().  */# define __set_errno(e) errno = (e)
# if !defined S_ISLNK && !HAVE_READLINK# ifndef MAXSYMLINKS
#  define lstat stat#  ifdef SYMLOOP_MAX
 #   define MAXSYMLINKS SYMLOOP_MAX
 #  else
 #   define MAXSYMLINKS 20
 #  endif
 # endif  # endif
 #endif  #endif
   
   #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
   # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
   #endif
   
   #if !FUNC_REALPATH_WORKS || defined _LIBC
 /* 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
Line 100  __realpath (const char *name, char *resolved) Line 100  __realpath (const char *name, char *resolved)
   char *rpath, *dest, *extra_buf = NULL;    char *rpath, *dest, *extra_buf = NULL;
   const char *start, *end, *rpath_limit;    const char *start, *end, *rpath_limit;
   long int path_max;    long int path_max;
 #if HAVE_READLINK  
   int num_links = 0;    int num_links = 0;
 #endif  
   
   if (name == NULL)    if (name == NULL)
     {      {
       /* As per Single Unix Specification V2 we must return an error if        /* As per Single Unix Specification V2 we must return an error if
         either parameter is a null pointer.  We extend this to allow         either parameter is a null pointer.  We extend this to allow
         the RESOLVED parameter to be NULL in case the we are expected to         the RESOLVED parameter to be NULL in case the we are expected to
         allocate the room for the return value.  */         allocate the room for the return value.  */
       __set_errno (EINVAL);        __set_errno (EINVAL);
       return NULL;        return NULL;
     }      }
Line 117  __realpath (const char *name, char *resolved) Line 115  __realpath (const char *name, char *resolved)
   if (name[0] == '\0')    if (name[0] == '\0')
     {      {
       /* As per Single Unix Specification V2 we must return an error if        /* As per Single Unix Specification V2 we must return an error if
         the name argument points to an empty string.  */         the name argument points to an empty string.  */
       __set_errno (ENOENT);        __set_errno (ENOENT);
       return NULL;        return NULL;
     }      }
Line 127  __realpath (const char *name, char *resolved) Line 125  __realpath (const char *name, char *resolved)
 #else  #else
   path_max = pathconf (name, _PC_PATH_MAX);    path_max = pathconf (name, _PC_PATH_MAX);
   if (path_max <= 0)    if (path_max <= 0)
    path_max = 1024;    path_max = 8192;
 #endif  #endif
   
   if (resolved == NULL)    if (resolved == NULL)
     {      {
       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          /* It's easier to set errno to ENOMEM than to rely on the
             'malloc-posix' gnulib module.  */             'malloc-posix' gnulib module.  */
          errno = ENOMEM;          errno = ENOMEM;
          return NULL;          return NULL;
        }        }
     }      }
   else    else
     rpath = resolved;      rpath = resolved;
Line 148  __realpath (const char *name, char *resolved) Line 146  __realpath (const char *name, char *resolved)
   if (name[0] != '/')    if (name[0] != '/')
     {      {
       if (!__getcwd (rpath, path_max))        if (!__getcwd (rpath, path_max))
        {        {
          rpath[0] = '\0';          rpath[0] = '\0';
          goto error;          goto error;
        }        }
       dest = strchr (rpath, '\0');        dest = strchr (rpath, '\0');
     }      }
   else    else
     {      {
       rpath[0] = '/';        rpath[0] = '/';
       dest = rpath + 1;        dest = rpath + 1;
         if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
           *dest++ = '/';
     }      }
   
   for (start = end = name; *start; start = end)    for (start = end = name; *start; start = end)
Line 167  __realpath (const char *name, char *resolved) Line 167  __realpath (const char *name, char *resolved)
 #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 (*start == '/')
        ++start;        ++start;
   
       /* Find end of path component.  */        /* Find end of path component.  */
       for (end = start; *end && *end != '/'; ++end)        for (end = start; *end && *end != '/'; ++end)
        /* Nothing.  */;        /* Nothing.  */;
   
       if (end - start == 0)        if (end - start == 0)
        break;        break;
       else if (end - start == 1 && start[0] == '.')        else if (end - start == 1 && start[0] == '.')
        /* nothing */;        /* nothing */;
       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 + 1)
            while ((--dest)[-1] != '/');            while ((--dest)[-1] != '/');
        }          if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
               && *dest == '/')
             dest++;
         }
       else        else
        {        {
          size_t new_size;          size_t new_size;
   
          if (dest[-1] != '/')          if (dest[-1] != '/')
            *dest++ = '/';            *dest++ = '/';
   
          if (dest + (end - start) >= rpath_limit)          if (dest + (end - start) >= rpath_limit)
            {            {
              ptrdiff_t dest_offset = dest - rpath;              ptrdiff_t dest_offset = dest - rpath;
              char *new_rpath;              char *new_rpath;
   
              if (resolved)              if (resolved)
                {                {
                  __set_errno (ENAMETOOLONG);                  __set_errno (ENAMETOOLONG);
                  if (dest > rpath + 1)                  if (dest > rpath + 1)
                    dest--;                    dest--;
                  *dest = '\0';                  *dest = '\0';
                  goto error;                  goto error;
                }                }
              new_size = rpath_limit - rpath;              new_size = rpath_limit - rpath;
              if (end - start + 1 > path_max)              if (end - start + 1 > path_max)
                new_size += end - start + 1;                new_size += end - start + 1;
              else              else
                new_size += path_max;                new_size += path_max;
              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                  /* It's easier to set errno to ENOMEM than to rely on the
                     'realloc-posix' gnulib module.  */                     'realloc-posix' gnulib module.  */
                  errno = ENOMEM;                  errno = ENOMEM;
                  goto error;                  goto error;
                }                }
              rpath = new_rpath;              rpath = new_rpath;
              rpath_limit = rpath + new_size;              rpath_limit = rpath + new_size;
   
              dest = rpath + dest_offset;              dest = rpath + dest_offset;
            }            }
   
 #ifdef _LIBC  #ifdef _LIBC
          dest = __mempcpy (dest, start, end - start);          dest = __mempcpy (dest, start, end - start);
 #else  #else
          memcpy (dest, start, end - start);          memcpy (dest, start, end - start);
          dest += end - start;          dest += end - start;
 #endif  #endif
          *dest = '\0';          *dest = '\0';
   
 #ifdef _LIBC  #ifdef _LIBC
          if (__lxstat64 (_STAT_VER, rpath, &st) < 0)          if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
 #else  #else
          if (lstat (rpath, &st) < 0)          if (lstat (rpath, &st) < 0)
 #endif  #endif
            goto error;            goto error;
   
#if HAVE_READLINK          if (S_ISLNK (st.st_mode))
          if (S_ISLNK (st.st_mode))            {
            {              char *buf;
              char *buf;              size_t len;
              size_t len; 
              int n; 
   
              if (++num_links > MAXSYMLINKS)              if (++num_links > MAXSYMLINKS)
                {                {
                  __set_errno (ELOOP);                  __set_errno (ELOOP);
                  goto error;                  goto error;
                }                }
   
              buf = malloca (path_max);              buf = malloca (path_max);
              if (!buf)              if (!buf)
                {                {
                  errno = ENOMEM;                  errno = ENOMEM;
                  goto error;                  goto error;
                }                }
   
              n = __readlink (rpath, buf, path_max - 1);              n = __readlink (rpath, buf, path_max - 1);
              if (n < 0)              if (n < 0)
                {                {
                  int saved_errno = errno;                  int saved_errno = errno;
                  freea (buf);                  freea (buf);
                  errno = saved_errno;                  errno = saved_errno;
                  goto error;                  goto error;
                }                }
              buf[n] = '\0';              buf[n] = '\0';
   
              if (!extra_buf)              if (!extra_buf)
                {                {
                  extra_buf = malloca (path_max);                  extra_buf = malloca (path_max);
                  if (!extra_buf)                  if (!extra_buf)
                    {                    {
                      freea (buf);                      freea (buf);
                      errno = ENOMEM;                      errno = ENOMEM;
                      goto error;                      goto error;
                    }                    }
                }                }
   
              len = strlen (end);              len = strlen (end);
              if ((long int) (n + len) >= path_max)              if ((long int) (n + len) >= path_max)
                {                {
                  freea (buf);                  freea (buf);
                  __set_errno (ENAMETOOLONG);                  __set_errno (ENAMETOOLONG);
                  goto error;                  goto error;
                }                }
   
              /* Careful here, end may be a pointer into extra_buf... */              /* Careful here, end may be a pointer into extra_buf... */
              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 (buf[0] == '/')
                dest = rpath + 1;       /* It's an absolute symlink */                {
              else                  dest = rpath + 1;     /* It's an absolute symlink */
                /* Back up to previous component, ignore if at root already: */                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
                if (dest > rpath + 1)                    *dest++ = '/';
                  while ((--dest)[-1] != '/');                }
            }              else
#endif                {
        }                  /* Back up to previous component, ignore if at root
                      already: */
                   if (dest > rpath + 1)
                     while ((--dest)[-1] != '/');
                   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
                       && *dest == '/')
                     dest++;
                 }
             }
           else if (!S_ISDIR (st.st_mode) && *end != '\0')
             {
               __set_errno (ENOTDIR);
               goto error;
             }
         }
     }      }
   if (dest > rpath + 1 && dest[-1] == '/')    if (dest > rpath + 1 && dest[-1] == '/')
     --dest;      --dest;
     if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
       dest++;
   *dest = '\0';    *dest = '\0';
   
   if (extra_buf)    if (extra_buf)
     freea (extra_buf);      freea (extra_buf);
   
  return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;  return rpath;
   
 error:  error:
   {    {
     int saved_errno = errno;      int saved_errno = errno;
     if (extra_buf)      if (extra_buf)
       freea (extra_buf);        freea (extra_buf);
    if (resolved)    if (resolved == NULL)
      strcpy (resolved, rpath); 
    else 
       free (rpath);        free (rpath);
     errno = saved_errno;      errno = saved_errno;
   }    }
   return NULL;    return NULL;
 }  }
 #ifdef _LIBC  
 versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);  versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
   
   
 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)  #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
 char *  char *
   attribute_compat_text_section
 __old_realpath (const char *name, char *resolved)  __old_realpath (const char *name, char *resolved)
 {  {
   if (resolved == NULL)    if (resolved == NULL)

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


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