summaryrefslogtreecommitdiff
path: root/lib/sh/getcwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sh/getcwd.c')
-rw-r--r--lib/sh/getcwd.c85
1 files changed, 64 insertions, 21 deletions
diff --git a/lib/sh/getcwd.c b/lib/sh/getcwd.c
index cd724f6..07eb817 100644
--- a/lib/sh/getcwd.c
+++ b/lib/sh/getcwd.c
@@ -1,22 +1,22 @@
-/* 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>
@@ -26,6 +26,10 @@
#pragma alloca
#endif /* _AIX && RISC6000 && !__GNUC__ */
+#if defined (__QNX__)
+# undef HAVE_LSTAT
+#endif
+
#include <bashtypes.h>
#include <errno.h>
@@ -44,6 +48,12 @@
#include <bashansi.h>
+#if defined (BROKEN_DIRENT_D_INO)
+# include "command.h"
+# include "general.h"
+# include "externs.h"
+#endif
+
#include <xmalloc.h>
#if !defined (errno)
@@ -58,6 +68,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.
@@ -169,7 +206,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;
@@ -251,19 +292,21 @@ getcwd (buf, size)
{
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_T) buf, (PTR_T) pathp, len);
}