[BACK]Return to getcwd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/gen/getcwd.c between version 1.1.1.2 and 1.24.6.2

version 1.1.1.2, 1995/02/25 09:11:43 version 1.24.6.2, 2002/11/11 22:22:09
Line 1 
Line 1 
   /*      $NetBSD$        */
   
 /*  /*
  * Copyright (c) 1989, 1991, 1993   * Copyright (c) 1989, 1991, 1993, 1995
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  *   *
    * This code is derived from software contributed to Berkeley by
    * Jan-Simon Pendry.
    *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
  * are met:   * are met:
Line 31 
Line 36 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
   #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)  #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getcwd.c    8.1 (Berkeley) 6/4/93";  #if 0
   static char sccsid[] = "@(#)getcwd.c    8.5 (Berkeley) 2/7/95";
   #else
   __RCSID("$NetBSD$");
   #endif
 #endif /* LIBC_SCCS and not lint */  #endif /* LIBC_SCCS and not lint */
   
   #include "namespace.h"
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/stat.h>  #include <sys/stat.h>
   
 #include <errno.h>  #include <assert.h>
 #include <dirent.h>  #include <dirent.h>
   #include <errno.h>
   #include <fcntl.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   
   #include "extern.h"
   
   #ifdef __weak_alias
   __weak_alias(getcwd,_getcwd)
   __weak_alias(realpath,_realpath)
   #endif
   
 #define ISDOT(dp) \  #define ISDOT(dp) \
         (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \          (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
             dp->d_name[1] == '.' && dp->d_name[2] == '\0'))              (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
   
   
   #if defined(__SVR4) || defined(__svr4__)
   #define d_fileno d_ino
   #endif
   
   /*
    * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
    *
    * Find the real name of path, by removing all ".", ".." and symlink
    * components.  Returns (resolved) on success, or (NULL) on failure,
    * in which case the path which caused trouble is left in (resolved).
    */
   char *
   realpath(path, resolved)
           const char *path;
           char *resolved;
   {
           struct stat sb;
           int fd, n, rootd, serrno, nlnk = 0;
           char *p, *q, wbuf[MAXPATHLEN];
   
           _DIAGASSERT(path != NULL);
           _DIAGASSERT(resolved != NULL);
   
           /* Save the starting point. */
           if ((fd = open(".", O_RDONLY)) < 0) {
                   (void)strcpy(resolved, ".");
                   return (NULL);
           }
   
           /*
            * Find the dirname and basename from the path to be resolved.
            * Change directory to the dirname component.
            * lstat the basename part.
            *     if it is a symlink, read in the value and loop.
            *     if it is a directory, then change to that directory.
            * get the current directory name and append the basename.
            */
           (void)strncpy(resolved, path, MAXPATHLEN - 1);
           resolved[MAXPATHLEN - 1] = '\0';
   loop:
           q = strrchr(resolved, '/');
           if (q != NULL) {
                   p = q + 1;
                   if (q == resolved)
                           q = "/";
                   else {
                           do {
                                   --q;
                           } while (q > resolved && *q == '/');
                           q[1] = '\0';
                           q = resolved;
                   }
                   if (chdir(q) < 0)
                           goto err1;
           } else
                   p = resolved;
   
           /* Deal with the last component. */
           if (lstat(p, &sb) == 0) {
                   if (S_ISLNK(sb.st_mode)) {
                           if (nlnk++ >= MAXSYMLINKS) {
                                   errno = ELOOP;
                                   goto err1;
                           }
                           n = readlink(p, resolved, MAXPATHLEN-1);
                           if (n < 0)
                                   goto err1;
                           resolved[n] = '\0';
                           goto loop;
                   }
                   if (S_ISDIR(sb.st_mode)) {
                           if (chdir(p) < 0)
                                   goto err1;
                           p = "";
                   }
           }
   
           /*
            * Save the last component name and get the full pathname of
            * the current directory.
            */
           (void)strlcpy(wbuf, p, sizeof(wbuf));
   
           /*
            * Call the inernal internal version of getcwd which
            * does a physical search rather than using the $PWD short-cut
            */
           if (getcwd(resolved, MAXPATHLEN) == 0)
                   goto err1;
   
           /*
            * Join the two strings together, ensuring that the right thing
            * happens if the last component is empty, or the dirname is root.
            */
           if (resolved[0] == '/' && resolved[1] == '\0')
                   rootd = 1;
           else
                   rootd = 0;
   
           if (*wbuf) {
                   if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
                           errno = ENAMETOOLONG;
                           goto err1;
                   }
                   if (rootd == 0)
                           (void)strcat(resolved, "/"); /* XXX: strcat is safe */
                   (void)strcat(resolved, wbuf);   /* XXX: strcat is safe */
           }
   
           /* Go back to where we came from. */
           if (fchdir(fd) < 0) {
                   serrno = errno;
                   goto err2;
           }
   
           /* It's okay if the close fails, what's an fd more or less? */
           (void)close(fd);
           return (resolved);
   
   err1:   serrno = errno;
           (void)fchdir(fd);
   err2:   (void)close(fd);
           errno = serrno;
           return (NULL);
   }
   
   #ifdef OLD_GETCWD
   
 char *  char *
 getcwd(pt, size)  getcwd(pt, size)
         char *pt;          char *pt;
         size_t size;          size_t size;
 {  {
         register struct dirent *dp;          struct dirent *dp;
         register DIR *dir;          DIR *dir;
         register dev_t dev;          dev_t dev;
         register ino_t ino;          ino_t ino;
         register int first;          int first;
         register char *bpt, *bup;          char *bpt, *bup;
         struct stat s;          struct stat s;
         dev_t root_dev;          dev_t root_dev;
         ino_t root_ino;          ino_t root_ino;
         size_t ptsize, upsize;          size_t ptsize, upsize;
         int save_errno;          int save_errno;
         char *ept, *eup, *up;          char *ept, *eup, *up;
           size_t dlen;
   
         /*          /*
          * If no buffer specified by the user, allocate one as necessary.           * If no buffer specified by the user, allocate one as necessary.
Line 90  getcwd(pt, size)
Line 240  getcwd(pt, size)
         /*          /*
          * Allocate bytes (1024 - malloc space) for the string of "../"'s.           * Allocate bytes (1024 - malloc space) for the string of "../"'s.
          * Should always be enough (it's 340 levels).  If it's not, allocate           * Should always be enough (it's 340 levels).  If it's not, allocate
          * as necessary.  Special * case the first stat, it's ".", not "..".           * as necessary.  Special case the first stat, it's ".", not "..".
          */           */
         if ((up = malloc(upsize = 1024 - 4)) == NULL)          if ((up = malloc(upsize = 1024 - 4)) == NULL)
                 goto err;                  goto err;
Line 124  getcwd(pt, size)
Line 274  getcwd(pt, size)
                          * path to the beginning of the buffer, but it's always                           * path to the beginning of the buffer, but it's always
                          * been that way and stuff would probably break.                           * been that way and stuff would probably break.
                          */                           */
                         (void)bcopy(bpt, pt, ept - bpt);                          memmove(pt, bpt,  (size_t)(ept - bpt));
                         free(up);                          free(up);
                         return (pt);                          return (pt);
                 }                  }
Line 161  getcwd(pt, size)
Line 311  getcwd(pt, size)
                         for (;;) {                          for (;;) {
                                 if (!(dp = readdir(dir)))                                  if (!(dp = readdir(dir)))
                                         goto notfound;                                          goto notfound;
                                 if (dp->d_fileno == ino)                                  if (dp->d_fileno == ino) {
   #if defined(__SVR4) || defined(__svr4__) || defined(__linux__)
                                           dlen = strlen(dp->d_name);
   #else
                                           dlen = dp->d_namlen;
   #endif
                                         break;                                          break;
                                   }
                         }                          }
                 } else                  } else
                         for (;;) {                          for (;;) {
Line 170  getcwd(pt, size)
Line 326  getcwd(pt, size)
                                         goto notfound;                                          goto notfound;
                                 if (ISDOT(dp))                                  if (ISDOT(dp))
                                         continue;                                          continue;
                                 bcopy(dp->d_name, bup, dp->d_namlen + 1);  #if defined(__SVR4) || defined(__svr4__) || defined(__linux__)
                                   dlen = strlen(dp->d_name);
   #else
                                   dlen = dp->d_namlen;
   #endif
                                   memmove(bup, dp->d_name, dlen + 1);
   
                                 /* Save the first error for later. */                                  /* Save the first error for later. */
                                 if (lstat(up, &s)) {                                  if (lstat(up, &s)) {
Line 187  getcwd(pt, size)
Line 348  getcwd(pt, size)
                  * Check for length of the current name, preceding slash,                   * Check for length of the current name, preceding slash,
                  * leading slash.                   * leading slash.
                  */                   */
                 if (bpt - pt <= dp->d_namlen + (first ? 1 : 2)) {                  if (bpt - pt <= dlen + (first ? 1 : 2)) {
                         size_t len, off;                          size_t len, off;
   
                         if (!ptsize) {                          if (!ptsize) {
Line 200  getcwd(pt, size)
Line 361  getcwd(pt, size)
                                 goto err;                                  goto err;
                         bpt = pt + off;                          bpt = pt + off;
                         ept = pt + ptsize;                          ept = pt + ptsize;
                         (void)bcopy(bpt, ept - len, len);                          memmove(ept - len, bpt, len);
                         bpt = ept - len;                          bpt = ept - len;
                 }                  }
                 if (!first)                  if (!first)
                         *--bpt = '/';                          *--bpt = '/';
                 bpt -= dp->d_namlen;                  bpt -= dlen;
                 bcopy(dp->d_name, bpt, dp->d_namlen);                  memmove(bpt, dp->d_name, dlen);
                 (void)closedir(dir);                  (void)closedir(dir);
   
                 /* Truncate any file name. */                  /* Truncate any file name. */
Line 228  err:
Line 389  err:
         free(up);          free(up);
         return (NULL);          return (NULL);
 }  }
   
   #else /* New getcwd */
   
   char *
   getcwd(pt, size)
           char *pt;
           size_t size;
   {
           size_t ptsize, bufsize;
           int len;
   
           /*
            * If no buffer specified by the user, allocate one as necessary.
            * If a buffer is specified, the size has to be non-zero.  The path
            * is built from the end of the buffer backwards.
            */
           if (pt) {
                   ptsize = 0;
                   if (!size) {
                           errno = EINVAL;
                           return (NULL);
                   }
                   bufsize = size;
           } else {
                   if ((pt = malloc(ptsize = 1024 - 4)) == NULL)
                           return (NULL);
                   bufsize = ptsize;
           }
           for (;;) {
                   len = __getcwd(pt, bufsize);
                   if ((len < 0) && (size == 0) && (errno == ERANGE)) {
                           if (ptsize > (MAXPATHLEN*4))
                                   return NULL;
                           if ((pt = realloc(pt, ptsize *= 2)) == NULL)
                                   return NULL;
                           bufsize = ptsize;
                           continue;
                   }
                   break;
           }
           if (len < 0)
                   return NULL;
           else
                   return pt;
   }
   
   #endif

Legend:
Removed from v.1.1.1.2  
changed lines
  Added in v.1.24.6.2

CVSweb <webmaster@jp.NetBSD.org>