1 /* getcwd.c -- get pathname of current directory */
3 /* Copyright (C) 1991 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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 Bush 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 Bush. 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 <bushtypes.h>
36 #if defined (HAVE_LIMITS_H)
40 #if defined (HAVE_UNISTD_H)
45 #include <posixstat.h>
51 #if !defined (D_FILENO_AVAILABLE)
52 # include "lxrgmr/command.h"
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");