1
/* getcwd.c -- get pathname of current directory */
3
/* Copyright (C) 1991 Free Software Foundation, Inc.
5
This file is part of GNU Bash, the Bourne Again SHell.
7
Bash is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
12
Bash is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Bash. If not, see <http://www.gnu.org/licenses/>.
23
#if !defined (HAVE_GETCWD)
25
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
27
#endif /* _AIX && RISC6000 && !__GNUC__ */
33
#include <bashtypes.h>
36
#if defined (HAVE_LIMITS_H)
40
#if defined (HAVE_UNISTD_H)
45
#include <posixstat.h>
51
#if !defined (D_FILENO_AVAILABLE)
63
#if !defined (HAVE_LSTAT)
71
/* If the d_fileno member of a struct dirent doesn't return anything useful,
72
we need to check inode number equivalence the hard way. Return 1 if
73
the inode corresponding to PATH/DIR is identical to THISINO. */
74
#if !defined (D_FILENO_AVAILABLE)
76
_path_checkino (dotp, name, thisino)
86
fullpath = sh_makepath (dotp, name, MP_RMDOT);
87
if (stat (fullpath, &st) < 0)
94
return (st.st_ino == thisino);
98
/* Get the pathname of the current working directory,
99
and put it in SIZE bytes of BUF. Returns NULL if the
100
directory couldn't be determined or SIZE was too small.
101
If successful, returns BUF. In GNU, if BUF is NULL,
102
an array is allocated with `malloc'; the array is SIZE
103
bytes long, unless SIZE <= 0, in which case it is as
105
#if defined (__STDC__)
107
getcwd (char *buf, size_t size)
108
#else /* !__STDC__ */
113
#endif /* !__STDC__ */
115
static const char dots[]
116
= "../../../../../../../../../../../../../../../../../../../../../../../\
117
../../../../../../../../../../../../../../../../../../../../../../../../../../\
118
../../../../../../../../../../../../../../../../../../../../../../../../../..";
119
const char *dotp, *dotlist;
121
dev_t rootdev, thisdev;
122
ino_t rootino, thisino;
123
char path[PATH_MAX + 1];
124
register char *pathp;
130
if (buf != NULL && size == 0)
133
return ((char *)NULL);
136
pathsize = sizeof (path);
137
pathp = &path[pathsize];
141
if (stat (".", &st) < 0)
142
return ((char *)NULL);
146
if (stat ("/", &st) < 0)
147
return ((char *)NULL);
153
dotsize = sizeof (dots) - 1;
154
dotp = &dots[sizeof (dots)];
156
while (!(thisdev == rootdev && thisino == rootino))
158
register DIR *dirstream;
159
register struct dirent *d;
165
/* Look at the parent directory. */
168
/* My, what a deep directory tree you have, Grandma. */
172
new = (char *)malloc (dotsize * 2 + 1);
175
memcpy (new, dots, dotsize);
179
new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
183
memcpy (&new[dotsize], new, dotsize);
184
dotp = &new[dotsize];
192
/* Figure out if this directory is a mount point. */
193
if (stat (dotp, &st) < 0)
197
mount_point = dotdev != thisdev;
199
/* Search for the last directory. */
200
dirstream = opendir (dotp);
201
if (dirstream == NULL)
203
while ((d = readdir (dirstream)) != NULL)
205
if (d->d_name[0] == '.' &&
206
(d->d_name[1] == '\0' ||
207
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
209
#if defined (D_FILENO_AVAILABLE)
210
if (mount_point || d->d_fileno == thisino)
212
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
217
namlen = D_NAMLEN(d);
219
alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
220
memcpy (name, dotp, dotlist + dotsize - dotp);
221
name[dotlist + dotsize - dotp] = '/';
222
memcpy (&name[dotlist + dotsize - dotp + 1],
223
d->d_name, namlen + 1);
224
if (lstat (name, &st) < 0)
228
(void) closedir (dirstream);
235
if (st.st_dev == thisdev && st.st_ino == thisino)
244
int save = errno ? errno : saved_errno;
246
(void) closedir (dirstream);
254
while ((space = pathp - pathbuf) <= namlen)
260
new = (char *)malloc (pathsize * 2);
266
new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
271
(void) memcpy (new + pathsize + space, pathp, pathsize - space);
272
pathp = new + pathsize + space;
278
(void) memcpy (pathp, d->d_name, namlen);
280
(void) closedir (dirstream);
287
if (pathp == &path[sizeof(path) - 1])
291
free ((PTR_T) dotlist);
294
size_t len = pathbuf + pathsize - pathp;
295
if (buf == NULL && size <= 0)
298
if ((size_t) size < len)
305
buf = (char *) malloc (size);
310
(void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
319
if ((dotlist != dots) && dotlist)
322
free ((PTR_T) dotlist);
327
if ((pathbuf != path) && pathbuf)
330
free ((PTR_T) pathbuf);
333
return ((char *)NULL);
344
if (getcwd(b, sizeof(b)))
351
perror ("cwd: getcwd");
356
#endif /* !HAVE_GETCWD */