gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/stdlib/realpath.cbare sourcepermlink (0.01 seconds)

Search this content:

    1: /*      $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */
    2: /*
    3:  * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  * 3. The names of the authors may not be used to endorse or promote
   14:  *    products derived from this software without specific prior written
   15:  *    permission.
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27:  * SUCH DAMAGE.
   28:  */
   29: 
   30: #include <sys/param.h>
   31: #include <sys/stat.h>
   32: 
   33: #include <errno.h>
   34: #include <stdlib.h>
   35: #include <string.h>
   36: #include <unistd.h>
   37: 
   38: /*
   39:  * char *realpath(const char *path, char resolved[PATH_MAX]);
   40:  *
   41:  * Find the real name of path, by removing all ".", ".." and symlink
   42:  * components.  Returns (resolved) on success, or (NULL) on failure,
   43:  * in which case the path which caused trouble is left in (resolved).
   44:  */
   45: char *
   46: realpath2_eno(const char *path1, const char *path, char *resolved, int *eno)
   47: {
   48:         /*struct stat sb;*/
   49:         char *p, *q, *s;
   50:         size_t left_len, resolved_len;
   51:         unsigned symlinks;
   52:         int serrno/*, slen*/, mem_allocated;
   53:         char left[PATH_MAX], next_token[PATH_MAX]/*, symlink[PATH_MAX]*/;
   54: 
   55:         if (path[0] == '\0') {
   56:                 /*errno*/serrno = ENOENT;
   57:                 goto e1;
   58:         }
   59: 
   60:         /*serrno = errno;*/
   61: 
   62:         if (resolved == NULL) {
   63:                 resolved = malloc(PATH_MAX);
   64:                 if (resolved == NULL)
   65:                         { serrno = ENOMEM; goto e1; }
   66:                 mem_allocated = 1;
   67:         } else
   68:                 mem_allocated = 0;
   69: 
   70:         symlinks = 0;
   71:         if (path[0] == '/') {
   72:                 resolved[0] = '/';
   73:                 resolved[1] = '\0';
   74:                 if (path[1] == '\0')
   75:                         return (resolved);
   76:                 resolved_len = 1;
   77:                 left_len = strlcpy(left, path + 1, sizeof(left));
   78:         } else {
   79:                 if ((serrno = (path1 != NULL ? (realpath2_eno(NULL, path1, resolved, eno) != NULL ? 0 : *eno) : __libc_getcwd(resolved, PATH_MAX) & 0xffff)) != 0) {
   80:                         if (mem_allocated)
   81:                                 free(resolved);
   82:                         else
   83:                                 strlcpy(resolved, ".", PATH_MAX);
   84:                         goto e1;
   85:                 }
   86:                 resolved_len = strlen(resolved);
   87:                 left_len = strlcpy(left, path, sizeof(left));
   88:         }
   89:         if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
   90:                 /*errno*/serrno = ENAMETOOLONG;
   91:                 goto err;
   92:         }
   93: 
   94:         /*
   95:          * Iterate over path components in `left'.
   96:          */
   97:         while (left_len != 0) {
   98:                 /*
   99:                  * Extract the next path component and adjust `left'
  100:                  * and its length.
  101:                  */
  102:                 p = strchr(left, '/');
  103:                 s = p ? p : left + left_len;
  104:                 if (s - left >= sizeof(next_token)) {
  105:                         /*errno*/serrno = ENAMETOOLONG;
  106:                         goto err;
  107:                 }
  108:                 memcpy(next_token, left, s - left);
  109:                 next_token[s - left] = '\0';
  110:                 left_len -= s - left;
  111:                 if (p != NULL)
  112:                         memmove(left, s + 1, left_len + 1);
  113:                 if (resolved[resolved_len - 1] != '/') {
  114:                         if (resolved_len + 1 >= PATH_MAX) {
  115:                                 /*errno*/serrno = ENAMETOOLONG;
  116:                                 goto err;
  117:                         }
  118:                         resolved[resolved_len++] = '/';
  119:                         resolved[resolved_len] = '\0';
  120:                 }
  121:                 if (next_token[0] == '\0')
  122:                         continue;
  123:                 else if (strcmp(next_token, ".") == 0)
  124:                         continue;
  125:                 else if (strcmp(next_token, "..") == 0) {
  126:                         /*
  127:                          * Strip the last path component except when we have
  128:                          * single "/"
  129:                          */
  130:                         if (resolved_len > 1) {
  131:                                 resolved[resolved_len - 1] = '\0';
  132:                                 q = strrchr(resolved, '/') + 1;
  133:                                 *q = '\0';
  134:                                 resolved_len = q - resolved;
  135:                         }
  136:                         continue;
  137:                 }
  138: 
  139:                 /*
  140:                  * Append the next path component and lstat() it. If
  141:                  * lstat() fails we still can return successfully if
  142:                  * there are no more path components left.
  143:                  */
  144:                 resolved_len = strlcat(resolved, next_token, PATH_MAX);
  145:                 if (resolved_len >= PATH_MAX) {
  146:                         /*errno*/serrno = ENAMETOOLONG;
  147:                         goto err;}
  148: #if 0
  149:                 if (lstat(resolved, &sb) != 0) {
  150:                         if (errno == ENOENT && p == NULL) {
  151:                                 errno = serrno;
  152:                                 return (resolved);
  153:                         }
  154:                         goto err;
  155:                 }
  156:                 if (S_ISLNK(sb.st_mode)) {
  157:                         if (symlinks++ > MAXSYMLINKS) {
  158:                                 /*errno*/serrno = ELOOP;
  159:                                 goto err;
  160:                         }
  161:                         slen = readlink(resolved, symlink, sizeof(symlink) - 1);
  162:                         if (slen < 0)
  163:                                 goto err;
  164:                         symlink[slen] = '\0';
  165:                         if (symlink[0] == '/') {
  166:                                 resolved[1] = 0;
  167:                                 resolved_len = 1;
  168:                         } else if (resolved_len > 1) {
  169:                                 /* Strip the last path component. */
  170:                                 resolved[resolved_len - 1] = '\0';
  171:                                 q = strrchr(resolved, '/') + 1;
  172:                                 *q = '\0';
  173:                                 resolved_len = q - resolved;
  174:                         }
  175: 
  176:                         /*
  177:                          * If there are any path components left, then
  178:                          * append them to symlink. The result is placed
  179:                          * in `left'.
  180:                          */
  181:                         if (p != NULL) {
  182:                                 if (symlink[slen - 1] != '/') {
  183:                                         if (slen + 1 >= sizeof(symlink)) {
  184:                                                 /*errno*/serrno = ENAMETOOLONG;
  185:                                                 goto err;
  186:                                         }
  187:                                         symlink[slen] = '/';
  188:                                         symlink[slen + 1] = 0;
  189:                                 }
  190:                                 left_len = strlcat(symlink, left, sizeof(left));
  191:                                 if (left_len >= sizeof(left)) {
  192:                                         /*errno*/serrno = ENAMETOOLONG;
  193:                                         goto err;
  194:                                 }
  195:                         }
  196:                         left_len = strlcpy(left, symlink, sizeof(left));}
  197: #endif
  198:         }
  199: 
  200:         /*
  201:          * Remove trailing slash except when the resolved pathname
  202:          * is a single "/".
  203:          */
  204:         if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
  205:                 resolved[resolved_len - 1] = '\0';
  206:         return (resolved);
  207: 
  208: err:
  209:         if (mem_allocated)
  210:                 free(resolved);
  211:         e1: if (eno) *eno = serrno; return NULL;
  212: } char *realpath2(const char *path1, const char *path2, char *resolved){return realpath2_eno(path1, path2, resolved, NULL);} char *realpath_eno(const char *path, char *resolved, int *eno){return realpath2_eno(NULL, path, resolved, eno);} char *realpath(const char *path, char *resolved){return realpath_eno(path, resolved, NULL);}