/[path-sandbox]/trunk/getcwd.c
Gentoo

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations) (download) (as text)
Wed Mar 2 09:04:45 2005 UTC (9 years, 5 months ago) by azarah
File MIME type: text/x-csrc
File size: 13758 byte(s)
White space fixes.

1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19 /* Wants:
20 AC_STDC_HEADERS
21 AC_DIR_HEADER
22 AC_UNISTD_H
23 AC_MEMORY_H
24 AC_CONST
25 AC_ALLOCA
26 */
27
28 /*
29 * $Header$
30 */
31
32 /* Modified: 26 July 2003; Martin Schlemmer <azarah@gentoo.org>
33 *
34 * Cleaned up unneeded stuff. Add a wrapper to try and detect when
35 * we have a kernel whose getcwd system call do not handle directory
36 * names longer than PATH_MAX, and if so, use our generic version.
37 * To work truly with > PATH_MAX lengh CWDs, I had to increase the
38 * size of the dots[] array. Also prepended a 'e' to functions that
39 * I did not rip out.
40 *
41 */
42
43 /* AIX requires this to be the first thing in the file. */
44 #if defined _AIX && !defined __GNUC__
45 #pragma alloca
46 #endif
47
48
49 #include <errno.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52
53 #ifdef STDC_HEADERS
54 # include <stddef.h>
55 #endif
56
57 #include "config.h"
58 #include <sys/param.h>
59 #include "localdecls.h"
60
61
62 #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
63 extern int errno;
64 #endif
65 #ifndef __set_errno
66 # define __set_errno(val) errno = (val)
67 #endif
68
69 #ifndef NULL
70 # define NULL 0
71 #endif
72
73 #if defined USGr3 && !defined DIRENT
74 # define DIRENT
75 #endif /* USGr3 */
76 #if defined Xenix && !defined SYSNDIR
77 # define SYSNDIR
78 #endif /* Xenix */
79
80 #if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__
81 # include <dirent.h>
82 # ifndef __GNU_LIBRARY__
83 # define D_NAMLEN(d) strlen((d)->d_name)
84 # else
85 # define HAVE_D_NAMLEN
86 # define D_NAMLEN(d) ((d)->d_namlen)
87 # endif
88 #else /* not POSIX or DIRENT */
89 # define dirent direct
90 # define D_NAMLEN(d) ((d)->d_namlen)
91 # define HAVE_D_NAMLEN
92 # if defined USG && !defined sgi
93 # if defined SYSNDIR
94 # include <sys/ndir.h>
95 # else /* Not SYSNDIR */
96 # include "ndir.h"
97 # endif /* SYSNDIR */
98 # else /* not USG */
99 # include <sys/dir.h>
100 # endif /* USG */
101 #endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
102
103 #if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__
104 # include <unistd.h>
105 #endif
106
107 #if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX
108 # include <stdlib.h>
109 # include <string.h>
110 # define ANSI_STRING
111 #else /* No standard headers. */
112
113 # ifdef USG
114
115 # include <string.h>
116 # ifdef NEED_MEMORY_H
117 # include <memory.h>
118 # endif
119 # define ANSI_STRING
120
121 # else /* Not USG. */
122
123 # ifdef NeXT
124
125 # include <string.h>
126
127 # else /* Not NeXT. */
128
129 # include <strings.h>
130
131 # ifndef bcmp
132 extern int bcmp();
133 # endif
134 # ifndef bzero
135 extern void bzero();
136 # endif
137 # ifndef bcopy
138 extern void bcopy();
139 # endif
140
141 # endif /* NeXT. */
142
143 # endif /* USG. */
144
145 extern char *malloc(), *realloc();
146 extern void free();
147
148 #endif /* Standard headers. */
149
150 #ifndef ANSI_STRING
151 # define memcpy(d, s, n) bcopy((s), (d), (n))
152 # define memmove memcpy
153 #endif /* Not ANSI_STRING. */
154
155 #ifndef MAX
156 # define MAX(a, b) ((a) < (b) ? (b) : (a))
157 #endif
158
159 #ifdef _LIBC
160 # ifndef mempcpy
161 # define mempcpy __mempcpy
162 # endif
163 # define HAVE_MEMPCPY 1
164 #endif
165
166 #if !defined __alloca && !defined __GNU_LIBRARY__
167
168 # ifdef __GNUC__
169 # undef alloca
170 # define alloca(n) __builtin_alloca (n)
171 # else /* Not GCC. */
172 # if defined sparc || defined HAVE_ALLOCA_H
173 # include <alloca.h>
174 # else /* Not sparc or HAVE_ALLOCA_H. */
175 # ifndef _AIX
176 extern char *alloca();
177 # endif /* Not _AIX. */
178 # endif /* sparc or HAVE_ALLOCA_H. */
179 # endif /* GCC. */
180
181 # define __alloca alloca
182
183 #endif
184
185 #if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__
186 # include <limits.h>
187 #else
188 # include <sys/param.h>
189 #endif
190
191 #ifndef PATH_MAX
192 # ifdef MAXPATHLEN
193 # define PATH_MAX MAXPATHLEN
194 # else
195 # define PATH_MAX 1024
196 # endif
197 #endif
198
199 #if !defined STDC_HEADERS && !defined __GNU_LIBRARY__
200 # undef size_t
201 # define size_t unsigned int
202 #endif
203
204 #if !__STDC__ && !defined const
205 # define const
206 #endif
207
208 #ifndef __GNU_LIBRARY__
209 # define __lstat stat
210 #endif
211
212 #ifndef _LIBC
213 # define __getcwd getcwd
214 #endif
215
216 #ifndef GETCWD_RETURN_TYPE
217 # define GETCWD_RETURN_TYPE char *
218 #endif
219
220 #ifndef __LIBC
221 # define __lstat lstat
222 # define __readdir readdir
223 # define __closedir closedir
224 #endif
225
226 /* Get the pathname of the current working directory, and put it in SIZE
227 bytes of BUF. Returns NULL if the directory couldn't be determined or
228 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
229 NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
230 unless SIZE == 0, in which case it is as big as necessary. */
231
232 GETCWD_RETURN_TYPE
233 __egetcwd(buf, size)
234 char *buf;
235 size_t size;
236 {
237 static const char dots[]
238 = "../../../../../../../../../../../../../../../../../../../../../../../\
239 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
240 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
241 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
242 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
243 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
244 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
245 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
246 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
247 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
248 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
249 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
250 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
251 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
252 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
253 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
254 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
255 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
256 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
257 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
258 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
259 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
260 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
261 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
262 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
263 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
264 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
265 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
266 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
267 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
268 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
269 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
270 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
271 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
272 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
273 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
274 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
275 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
276 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
277 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
278 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
279 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
280 const char *dotp = &dots[sizeof (dots)];
281 const char *dotlist = dots;
282 size_t dotsize = sizeof (dots) - 1;
283 dev_t rootdev, thisdev;
284 ino_t rootino, thisino;
285 char *path;
286 register char *pathp;
287 struct stat st;
288 int prev_errno = errno;
289 size_t allocated = size;
290
291 if (size == 0) {
292 if (buf != NULL) {
293 __set_errno(EINVAL);
294 return NULL;
295 }
296
297 allocated = SB_PATH_MAX + 1;
298 }
299
300 if (buf != NULL)
301 path = buf;
302 else {
303 path = malloc(allocated);
304 if (path == NULL)
305 return NULL;
306 }
307
308 pathp = path + allocated;
309 *--pathp = '\0';
310
311 if (__lstat(".", &st) < 0)
312 goto lose2;
313 thisdev = st.st_dev;
314 thisino = st.st_ino;
315
316 if (__lstat("/", &st) < 0)
317 goto lose2;
318 rootdev = st.st_dev;
319 rootino = st.st_ino;
320
321 while (!(thisdev == rootdev && thisino == rootino)) {
322 register DIR *dirstream;
323 struct dirent *d;
324 dev_t dotdev;
325 ino_t dotino;
326 char mount_point;
327
328 /* Look at the parent directory. */
329 if (dotp == dotlist) {
330 /* My, what a deep directory tree you have, Grandma. */
331 char *new;
332 if (dotlist == dots) {
333 new = malloc(dotsize * 2 + 1);
334 if (new == NULL)
335 goto lose;
336 #ifdef HAVE_MEMPCPY
337 dotp = (char *)mempcpy(new, dots, dotsize);
338 #else
339 memcpy(new, dots, dotsize);
340 dotp = &new[dotsize];
341 #endif
342 } else {
343 new = realloc((__ptr_t) dotlist, dotsize * 2 + 1);
344 if (new == NULL)
345 goto lose;
346 dotp = &new[dotsize];
347 }
348 #ifdef HAVE_MEMPCPY
349 *((char *) mempcpy((char *) dotp, new, dotsize)) = '\0';
350 dotsize *= 2;
351 #else
352 memcpy((char *) dotp, new, dotsize);
353 dotsize *= 2;
354 new[dotsize] = '\0';
355 #endif
356 dotlist = new;
357 }
358
359 dotp -= 3;
360
361 /* Figure out if this directory is a mount point. */
362 if (__lstat(dotp, &st) < 0)
363 goto lose;
364 dotdev = st.st_dev;
365 dotino = st.st_ino;
366 mount_point = dotdev != thisdev;
367
368 /* Search for the last directory. */
369 #ifdef OUTSIDE_LIBSANDBOX
370 dirstream = opendir(dotp);
371 #else
372 dirstream = true_opendir(dotp);
373 #endif
374 if (dirstream == NULL)
375 goto lose;
376 /* Clear errno to distinguish EOF from error if readdir returns
377 NULL. */
378 __set_errno(0);
379 while ((d = __readdir(dirstream)) != NULL) {
380 if (d->d_name[0] == '.' &&
381 (d->d_name[1] == '\0'
382 || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
383 continue;
384 if (mount_point || (ino_t) d->d_ino == thisino) {
385 char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN(d)];
386 #ifdef HAVE_MEMPCPY
387 char *tmp = mempcpy(name, dotp,
388 dotlist + dotsize - dotp);
389 *tmp++ = '/';
390 strcpy(tmp, d->d_name);
391 #else
392 memcpy(name, dotp, dotlist + dotsize - dotp);
393 name[dotlist + dotsize - dotp] = '/';
394 strcpy(&name[dotlist + dotsize - dotp + 1], d->d_name);
395 #endif
396 /* We don't fail here if we cannot stat() a directory entry.
397 This can happen when (network) filesystems fail. If this
398 entry is in fact the one we are looking for we will find
399 out soon as we reach the end of the directory without
400 having found anything. */
401 if (__lstat(name, &st) >= 0 && st.st_dev == thisdev
402 && st.st_ino == thisino)
403 break;
404 }
405 }
406 if (d == NULL) {
407 int save = errno;
408 (void) __closedir(dirstream);
409 if (save == 0)
410 /* EOF on dirstream, which means that the current directory
411 has been removed. */
412 save = ENOENT;
413 __set_errno(save);
414 goto lose;
415 } else {
416 size_t namlen = _D_EXACT_NAMLEN(d);
417
418 if ((size_t) (pathp - path) <= namlen) {
419 if (size != 0) {
420 (void) __closedir(dirstream);
421 __set_errno(ERANGE);
422 goto lose;
423 } else {
424 char *tmp;
425 size_t oldsize = allocated;
426
427 allocated = 2 * MAX(allocated, namlen);
428 tmp = realloc(path, allocated);
429 if (tmp == NULL) {
430 (void) __closedir(dirstream);
431 __set_errno(ENOMEM); /* closedir might have changed it. */
432 goto lose;
433 }
434
435 /* Move current contents up to the end of the buffer.
436 This is guaranteed to be non-overlapping. */
437 pathp = memcpy(tmp + allocated -
438 (path + oldsize - pathp),
439 tmp + (pathp - path), path + oldsize - pathp);
440 path = tmp;
441 }
442 }
443 pathp -= namlen;
444 (void) memcpy(pathp, d->d_name, namlen);
445 *--pathp = '/';
446 (void) __closedir(dirstream);
447 }
448
449 thisdev = dotdev;
450 thisino = dotino;
451 }
452
453 if (pathp == &path[allocated - 1])
454 *--pathp = '/';
455
456 if (dotlist != dots)
457 free((__ptr_t) dotlist);
458
459 memmove(path, pathp, path + allocated - pathp);
460
461 /* Restore errno on successful return. */
462 __set_errno(prev_errno);
463
464 return path;
465
466 lose:
467 if (dotlist != dots)
468 free((__ptr_t) dotlist);
469 lose2:
470 if (buf == NULL)
471 free(path);
472 return NULL;
473 }
474
475 GETCWD_RETURN_TYPE
476 egetcwd(buf, size)
477 char *buf;
478 size_t size;
479 {
480 struct stat st;
481 char *tmpbuf;
482
483 __set_errno(0);
484 tmpbuf = getcwd(buf, size);
485
486 if (tmpbuf) {
487 __lstat(buf, &st);
488 } else {
489 return tmpbuf;
490 }
491
492 if (errno) {
493 /* If lstat() failed with eerror = ENOENT, then its
494 * possible that we are running on an older kernel,
495 * so use our generic version which *should* not fail.
496 */
497 if (errno == ENOENT) {
498 return __egetcwd(buf, size);
499 } else {
500 return tmpbuf;
501 }
502 }
503
504 return tmpbuf;
505 }
506
507 // vim:noexpandtab noai:cindent ai

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20