[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.7 and 1.8

version 1.7, 1997/07/21 14:07:04 version 1.8, 1998/02/02 02:41:23
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $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 36 
Line 39 
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)  #if defined(LIBC_SCCS) && !defined(lint)
 #if 0  #if 0
 static char sccsid[] = "@(#)getcwd.c    8.1 (Berkeley) 6/4/93";  static char sccsid[] = "@(#)getcwd.c    8.5 (Berkeley) 2/7/95";
 #else  #else
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
 #endif  #endif
Line 45  __RCSID("$NetBSD$");
Line 48  __RCSID("$NetBSD$");
 #include "namespace.h"  #include "namespace.h"
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <errno.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>
Line 56  __RCSID("$NetBSD$");
Line 61  __RCSID("$NetBSD$");
 __weak_alias(getcwd,_getcwd);  __weak_alias(getcwd,_getcwd);
 #endif  #endif
   
   static char *getcwd_physical __P((char *, size_t));
   
 #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')))
Line 65  getcwd(pt, size)
Line 72  getcwd(pt, size)
         char *pt;          char *pt;
         size_t size;          size_t size;
 {  {
           char *pwd;
           size_t pwdlen;
           dev_t dev;
           ino_t ino;
           struct stat s;
   
           /* Check $PWD -- if it's right, it's fast. */
           if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/' && !stat(pwd, &s)) {
                   dev = s.st_dev;
                   ino = s.st_ino;
                   if (!stat(".", &s) && dev == s.st_dev && ino == s.st_ino) {
                           pwdlen = strlen(pwd);
                           if (size != 0) {
                                   if (pwdlen + 1 > size) {
                                           errno = ERANGE;
                                           return (NULL);
                                   }
                           } else if ((pt = malloc(pwdlen + 1)) == NULL)
                                   return (NULL);
                           memmove(pt, pwd, pwdlen);
                           pt[pwdlen] = '\0';
                           return (pt);
                   }
           }
   
           return (getcwd_physical(pt, size));
   }
   
   /*
    * 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;
           char *p, *q, wbuf[MAXPATHLEN];
   
           /* 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)) {
                           n = readlink(p, resolved, MAXPATHLEN);
                           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)strcpy(wbuf, p);
   
           /*
            * Call the inernal internal version of getcwd which
            * does a physical search rather than using the $PWD short-cut
            */
           if (getcwd_physical(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, "/");
                   (void)strcat(resolved, wbuf);
           }
   
           /* 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);
   }
   
   static char *
   getcwd_physical(pt, size)
           char *pt;
           size_t size;
   {
         register struct dirent *dp;          register struct dirent *dp;
         register DIR *dir;          register DIR *dir;
         register dev_t dev;          register dev_t dev;
Line 101  getcwd(pt, size)
Line 256  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;

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

CVSweb <webmaster@jp.NetBSD.org>