1 /* getcwd.c -- stolen from the GNU C library and modified to work with bash. */
3 /* Copyright (C) 1991 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc.,
19 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #if !defined (HAVE_GETCWD)
25 #include <bashtypes.h>
28 #if defined (HAVE_LIMITS_H)
32 #if defined (HAVE_UNISTD_H)
37 #include <posixstat.h>
49 #if !defined (HAVE_LSTAT)
57 /* Get the pathname of the current working directory,
58 and put it in SIZE bytes of BUF. Returns NULL if the
59 directory couldn't be determined or SIZE was too small.
60 If successful, returns BUF. In GNU, if BUF is NULL,
61 an array is allocated with `malloc'; the array is SIZE
62 bytes long, unless SIZE <= 0, in which case it is as
64 #if defined (__STDC__)
66 getcwd (char *buf, size_t size)
72 #endif /* !__STDC__ */
74 static const char dots[]
75 = "../../../../../../../../../../../../../../../../../../../../../../../\
76 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
77 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
78 const char *dotp, *dotlist;
80 dev_t rootdev, thisdev;
81 ino_t rootino, thisino;
82 char path[PATH_MAX + 1];
89 if (buf != NULL && size == 0)
92 return ((char *)NULL);
95 pathsize = sizeof (path);
96 pathp = &path[pathsize];
100 if (stat (".", &st) < 0)
101 return ((char *)NULL);
105 if (stat ("/", &st) < 0)
106 return ((char *)NULL);
112 dotsize = sizeof (dots) - 1;
113 dotp = &dots[sizeof (dots)];
115 while (!(thisdev == rootdev && thisino == rootino))
117 register DIR *dirstream;
118 register struct dirent *d;
124 /* Look at the parent directory. */
127 /* My, what a deep directory tree you have, Grandma. */
131 new = (char *)malloc (dotsize * 2 + 1);
134 memcpy (new, dots, dotsize);
138 new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
142 memcpy (&new[dotsize], new, dotsize);
143 dotp = &new[dotsize];
151 /* Figure out if this directory is a mount point. */
152 if (stat (dotp, &st) < 0)
156 mount_point = dotdev != thisdev;
158 /* Search for the last directory. */
159 dirstream = opendir (dotp);
160 if (dirstream == NULL)
162 while ((d = readdir (dirstream)) != NULL)
164 if (d->d_name[0] == '.' &&
165 (d->d_name[1] == '\0' ||
166 (d->d_name[1] == '.' && d->d_name[2] == '\0')))
168 if (mount_point || d->d_fileno == thisino)
172 namlen = D_NAMLEN(d);
174 alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
175 memcpy (name, dotp, dotlist + dotsize - dotp);
176 name[dotlist + dotsize - dotp] = '/';
177 memcpy (&name[dotlist + dotsize - dotp + 1],
178 d->d_name, namlen + 1);
179 if (lstat (name, &st) < 0)
183 (void) closedir (dirstream);
190 if (st.st_dev == thisdev && st.st_ino == thisino)
199 int save = errno ? errno : saved_errno;
201 (void) closedir (dirstream);
209 while ((space = pathp - pathbuf) <= namlen)
215 new = (char *)malloc (pathsize * 2);
221 new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
226 (void) memcpy (new + pathsize + space, pathp, pathsize - space);
227 pathp = new + pathsize + space;
233 (void) memcpy (pathp, d->d_name, namlen);
235 (void) closedir (dirstream);
242 if (pathp == &path[sizeof(path) - 1])
246 free ((PTR_T) dotlist);
249 size_t len = pathbuf + pathsize - pathp;
252 if (len < (size_t) size)
254 buf = (char *) malloc (len);
258 else if ((size_t) size < len)
263 (void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
272 if ((dotlist != dots) && dotlist)
275 free ((PTR_T) dotlist);
280 if ((pathbuf != path) && pathbuf)
283 free ((PTR_T) pathbuf);
286 return ((char *)NULL);
297 if (getcwd(b, sizeof(b)))
304 perror ("cwd: getcwd");
309 #endif /* !HAVE_GETCWD */