home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / wustl-ftpdaemon / src / realpath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  5.0 KB  |  170 lines

  1. /* Copyright (c) 1993, 1994  Washington University in Saint Louis
  2.  * All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions are
  6.  * met: 1. Redistributions of source code must retain the above copyright
  7.  * notice, this list of conditions and the following disclaimer. 2.
  8.  * Redistributions in binary form must reproduce the above copyright notice,
  9.  * this list of conditions and the following disclaimer in the documentation
  10.  * and/or other materials provided with the distribution. 3. All advertising
  11.  * materials mentioning features or use of this software must display the
  12.  * following acknowledgement: This product includes software developed by the
  13.  * Washington University in Saint Louis and its contributors. 4. Neither the
  14.  * name of the University nor the names of its contributors may be used to
  15.  * endorse or promote products derived from this software without specific
  16.  * prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
  19.  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21.  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASHINGTON
  22.  * UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  28.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31.  
  32. #include "config.h"
  33.  
  34. #include <stdio.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include <sys/param.h>
  38. #include <string.h>
  39.  
  40. #ifndef HAVE_SYMLINK
  41. #define lstat stat
  42. #endif
  43.  
  44. #ifdef AMIGA
  45. #include <proto/usergroup.h>
  46. #endif
  47.  
  48. char *
  49. realpath(char *pathname, char *result)
  50. {
  51.     struct stat sbuf;
  52.     char curpath[MAXPATHLEN],
  53.       workpath[MAXPATHLEN],
  54.       linkpath[MAXPATHLEN],
  55.       namebuf[MAXPATHLEN],
  56.      *where,
  57.      *ptr,
  58.      *last;
  59.     int len;
  60.  
  61.     strcpy(curpath, pathname);
  62.  
  63.     if (*pathname != '/') {
  64.         uid_t userid;
  65.         
  66. #ifdef HAVE_GETCWD
  67.     if (!getcwd(workpath,MAXPATHLEN)) {
  68. #else
  69.         if (!getwd(workpath)) {
  70. #endif    
  71.         userid = geteuid();
  72.         seteuid(0);
  73. #ifdef HAVE_GETCWD
  74.             if (!getcwd(workpath,MAXPATHLEN)) {
  75. #else
  76.             if (!getwd(workpath)) {
  77. #endif
  78. #ifndef AMIGA
  79.                 strcpy(result, ".");
  80. #else
  81.                     result[0] = 0;
  82. #endif
  83.             seteuid(userid);
  84.                 return (NULL);
  85.             }
  86.         seteuid(userid);
  87.     }
  88.     } else
  89.         *workpath = NULL;
  90.  
  91.     /* curpath is the path we're still resolving      */
  92.     /* linkpath is the path a symbolic link points to */
  93.     /* workpath is the path we've resolved            */
  94.  
  95.   loop:
  96.     where = curpath;
  97.     while (*where != NULL) {
  98.         if (!strcmp(where, ".")) {
  99.             where++;
  100.             continue;
  101.         }
  102.         /* deal with "./" */
  103.         if (!strncmp(where, "./", 2)) {
  104.             where += 2;
  105.             continue;
  106.         }
  107.         /* deal with "../" */
  108.         if (!strncmp(where, "../", 3)) {
  109.             where += 3;
  110.             ptr = last = workpath;
  111.             while (*ptr) {
  112.                 if (*ptr == '/')
  113.                     last = ptr;
  114.                 ptr++;
  115.             }
  116.             *last = NULL;
  117.             continue;
  118.         }
  119.         ptr = strchr(where, '/');
  120.         if (!ptr)
  121.             ptr = where + strlen(where) - 1;
  122.         else
  123.             *ptr = NULL;
  124.  
  125.         strcpy(namebuf, workpath);
  126.         for (last = namebuf; *last; last++)
  127.             continue;
  128.         if (*--last != '/')
  129.             strcat(namebuf, "/");
  130.         strcat(namebuf, where);
  131.  
  132.         where = ++ptr;
  133.         if (lstat(namebuf, &sbuf) == -1) {
  134.             strcpy(result, namebuf);
  135.             return (NULL);
  136.         }
  137.         /* was IFLNK */
  138. #ifdef HAVE_SYMLINK
  139.         if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
  140.             len = readlink(namebuf, linkpath, MAXPATHLEN);
  141.             if (len == 0) {
  142.                 strcpy(result, namebuf);
  143.                 return (NULL);
  144.             }
  145.             *(linkpath + len) = NULL;   /* readlink doesn't null-terminate
  146.                                          * result */
  147.             if (*linkpath == '/')
  148.                 *workpath = NULL;
  149.             if (*where) {
  150.                 strcat(linkpath, "/");
  151.                 strcat(linkpath, where);
  152.             }
  153.             strcpy(curpath, linkpath);
  154.             goto loop;
  155.         }
  156. #endif
  157.         if ((sbuf.st_mode & S_IFDIR) == S_IFDIR) {
  158.             strcpy(workpath, namebuf);
  159.             continue;
  160.         }
  161.         if (*where) {
  162.             strcpy(result, namebuf);
  163.             return (NULL);      /* path/notadir/morepath */
  164.         } else
  165.             strcpy(workpath, namebuf);
  166.     }
  167.     strcpy(result, workpath);
  168.     return (result);
  169. }
  170.