Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / lib / sh / getcwd.c
index d39655d..84799bb 100644 (file)
@@ -1,27 +1,35 @@
-/* getcwd.c -- stolen from the GNU C library and modified to work with bash. */
+/* getcwd.c -- get pathname of current directory */
 
 /* Copyright (C) 1991 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   This file is part of GNU Bash, the Bourne Again SHell.
 
-   The GNU C Library is distributed in the hope that it will be useful,
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place, Suite 330, Boston, MA 02111 USA.  */
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 #include <config.h>
 
 #if !defined (HAVE_GETCWD)
 
+#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
+  #pragma alloca
+#endif /* _AIX && RISC6000 && !__GNUC__ */
+
+#if defined (__QNX__)
+#  undef HAVE_LSTAT
+#endif
+
 #include <bashtypes.h>
 #include <errno.h>
 
 
 #include <bashansi.h>
 
+#include <xmalloc.h>
+
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
 
-#if defined (__STDC__)
-#  define CONST const
-#  define PTR void *
-#else /* !__STDC__ */
-#  define CONST
-#  define PTR char *
-#endif /* !__STDC__ */
-
-#if !defined (PATH_MAX)
-#  if defined (MAXPATHLEN)
-#    define PATH_MAX MAXPATHLEN
-#  else /* !MAXPATHLEN */
-#    define PATH_MAX 1024
-#  endif /* !MAXPATHLEN */
-#endif /* !PATH_MAX */
-
 #if !defined (HAVE_LSTAT)
 #  define lstat stat
 #endif
@@ -68,6 +62,33 @@ extern int errno;
 #  define NULL 0
 #endif
 
+/* If the d_fileno member of a struct dirent doesn't return anything useful,
+   we need to check inode number equivalence the hard way.  Return 1 if
+   the inode corresponding to PATH/DIR is identical to THISINO. */
+#if defined (BROKEN_DIRENT_D_INO)
+static int
+_path_checkino (dotp, name, thisino)
+     char *dotp;
+     char *name;
+     ino_t thisino;
+{
+  char *fullpath;
+  int r, e;
+  struct stat st;
+
+  e = errno;
+  fullpath = sh_makepath (dotp, name, MP_RMDOT);
+  if (stat (fullpath, &st) < 0)
+    {
+      errno = e;
+      return 0;
+    }
+  free (fullpath);
+  errno = e;
+  return (st.st_ino == thisino);
+}
+#endif
+    
 /* Get the pathname of the current working directory,
    and put it in SIZE bytes of BUF.  Returns NULL if the
    directory couldn't be determined or SIZE was too small.
@@ -85,11 +106,11 @@ getcwd (buf, size)
      size_t size;
 #endif /* !__STDC__ */
 {
-  static CONST char dots[]
+  static const char dots[]
     = "../../../../../../../../../../../../../../../../../../../../../../../\
 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
-  CONST char *dotp, *dotlist;
+  const char *dotp, *dotlist;
   size_t dotsize;
   dev_t rootdev, thisdev;
   ino_t rootino, thisino;
@@ -149,7 +170,7 @@ getcwd (buf, size)
            }
          else
            {
-             new = (char *)realloc ((PTR) dotlist, dotsize * 2 + 1);
+             new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
              if (new == NULL)
                goto lose;
            }
@@ -179,7 +200,11 @@ getcwd (buf, size)
              (d->d_name[1] == '\0' ||
                (d->d_name[1] == '.' && d->d_name[2] == '\0')))
            continue;
+#if !defined (BROKEN_DIRENT_D_INO)
          if (mount_point || d->d_fileno == thisino)
+#else
+         if (mount_point || _path_checkino (dotp, d->d_name, thisino))
+#endif
            {
              char *name;
 
@@ -232,7 +257,7 @@ getcwd (buf, size)
                }
              else
                {
-                 new = (char *)realloc ((PTR) pathbuf, (pathsize * 2));
+                 new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
                  if (!new)
                    goto lose;
                  pathp = new + space;
@@ -257,24 +282,26 @@ getcwd (buf, size)
     *--pathp = '/';
 
   if (dotlist != dots)
-    free ((PTR) dotlist);
+    free ((PTR_T) dotlist);
 
   {
     size_t len = pathbuf + pathsize - pathp;
+    if (buf == NULL && size <= 0)
+      size = len;
+
+    if ((size_t) size < len)
+      {
+       errno = ERANGE;
+       goto lose2;
+      }
     if (buf == NULL)
       {
-       if (len < (size_t) size)
-         len = size;
-       buf = (char *) malloc (len);
+       buf = (char *) malloc (size);
        if (buf == NULL)
          goto lose2;
       }
-    else if ((size_t) size < len)
-      {
-       errno = ERANGE;
-       goto lose2;
-      }
-    (void) memcpy((PTR) buf, (PTR) pathp, len);
+
+    (void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
   }
 
   if (pathbuf != path)
@@ -286,7 +313,7 @@ getcwd (buf, size)
   if ((dotlist != dots) && dotlist)
     {
       int e = errno;
-      free ((PTR) dotlist);
+      free ((PTR_T) dotlist);
       errno = e;
     }
 
@@ -294,7 +321,7 @@ getcwd (buf, size)
   if ((pathbuf != path) && pathbuf)
     {
       int e = errno;
-      free ((PTR) pathbuf);
+      free ((PTR_T) pathbuf);
       errno = e;
     }
   return ((char *)NULL);