]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/sh/getcwd.c
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., 675 Mass Ave,
19 Cambridge, MA 02139, 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>
47 #if defined (__STDC__)
53 #endif /* !__STDC__ */
55 #if !defined (PATH_MAX)
56 # if defined (MAXPATHLEN)
57 # define PATH_MAX MAXPATHLEN
58 # else /* !MAXPATHLEN */
59 # define PATH_MAX 1024
60 # endif /* !MAXPATHLEN */
61 #endif /* !PATH_MAX */
63 #if !defined (HAVE_LSTAT)
67 /* Get the pathname of the current working directory,
68 and put it in SIZE bytes of BUF. Returns NULL if the
69 directory couldn't be determined or SIZE was too small.
70 If successful, returns BUF. In GNU, if BUF is NULL,
71 an array is allocated with `malloc'; the array is SIZE
72 bytes long, unless SIZE <= 0, in which case it is as
74 #if defined (__STDC__)
76 getcwd (char *buf
, size_t size
)
82 #endif /* !__STDC__ */
84 static CONST
char dots
[]
85 = "../../../../../../../../../../../../../../../../../../../../../../../\
86 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
87 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
88 CONST
char *dotp
, *dotlist
;
90 dev_t rootdev
, thisdev
;
91 ino_t rootino
, thisino
;
92 char path
[PATH_MAX
+ 1];
99 if (buf
!= NULL
&& size
== 0)
102 return ((char *)NULL
);
105 pathsize
= sizeof (path
);
106 pathp
= &path
[pathsize
];
110 if (stat (".", &st
) < 0)
111 return ((char *)NULL
);
115 if (stat ("/", &st
) < 0)
116 return ((char *)NULL
);
122 dotsize
= sizeof (dots
) - 1;
123 dotp
= &dots
[sizeof (dots
)];
125 while (!(thisdev
== rootdev
&& thisino
== rootino
))
127 register DIR *dirstream
;
128 register struct dirent
*d
;
134 /* Look at the parent directory. */
137 /* My, what a deep directory tree you have, Grandma. */
141 new = malloc (dotsize
* 2 + 1);
144 memcpy (new, dots
, dotsize
);
148 new = realloc ((PTR
) dotlist
, dotsize
* 2 + 1);
152 memcpy (&new[dotsize
], new, dotsize
);
153 dotp
= &new[dotsize
];
161 /* Figure out if this directory is a mount point. */
162 if (stat (dotp
, &st
) < 0)
166 mount_point
= dotdev
!= thisdev
;
168 /* Search for the last directory. */
169 dirstream
= opendir (dotp
);
170 if (dirstream
== NULL
)
172 while ((d
= readdir (dirstream
)) != NULL
)
174 if (d
->d_name
[0] == '.' &&
175 (d
->d_name
[1] == '\0' ||
176 (d
->d_name
[1] == '.' && d
->d_name
[2] == '\0')))
178 if (mount_point
|| d
->d_fileno
== thisino
)
182 namlen
= D_NAMLEN(d
);
184 alloca (dotlist
+ dotsize
- dotp
+ 1 + namlen
+ 1);
185 memcpy (name
, dotp
, dotlist
+ dotsize
- dotp
);
186 name
[dotlist
+ dotsize
- dotp
] = '/';
187 memcpy (&name
[dotlist
+ dotsize
- dotp
+ 1],
188 d
->d_name
, namlen
+ 1);
189 if (lstat (name
, &st
) < 0)
193 (void) closedir (dirstream
);
200 if (st
.st_dev
== thisdev
&& st
.st_ino
== thisino
)
209 int save
= errno
? errno
: saved_errno
;
211 (void) closedir (dirstream
);
219 while ((space
= pathp
- pathbuf
) <= namlen
)
225 new = malloc (pathsize
* 2);
231 new = realloc ((PTR
) pathbuf
, (pathsize
* 2));
236 (void) memcpy (new + pathsize
+ space
, pathp
, pathsize
- space
);
237 pathp
= new + pathsize
+ space
;
243 (void) memcpy (pathp
, d
->d_name
, namlen
);
245 (void) closedir (dirstream
);
252 if (pathp
== &path
[sizeof(path
) - 1])
256 free ((PTR
) dotlist
);
259 size_t len
= pathbuf
+ pathsize
- pathp
;
262 if (len
< (size_t) size
)
264 buf
= (char *) malloc (len
);
268 else if ((size_t) size
< len
)
273 (void) memcpy((PTR
) buf
, (PTR
) pathp
, len
);
282 if ((dotlist
!= dots
) && dotlist
)
285 free ((PTR
) dotlist
);
290 if ((pathbuf
!= path
) && pathbuf
)
293 free ((PTR
) pathbuf
);
296 return ((char *)NULL
);
307 if (getcwd(b
, sizeof(b
)))
314 perror ("cwd: getcwd");
319 #endif /* !HAVE_GETCWD */