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

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download) (as text)
Fri Nov 19 22:03:42 2004 UTC (9 years, 11 months ago) by ferringb
File MIME type: text/x-csrc
File size: 14055 byte(s)
Initial revision

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 #ifdef HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <errno.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55
56 #ifdef STDC_HEADERS
57 # include <stddef.h>
58 #endif
59
60 #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
61 extern int errno;
62 #endif
63 #ifndef __set_errno
64 # define __set_errno(val) errno = (val)
65 #endif
66
67 #ifndef NULL
68 # define NULL 0
69 #endif
70
71 #if defined USGr3 && !defined DIRENT
72 # define DIRENT
73 #endif /* USGr3 */
74 #if defined Xenix && !defined SYSNDIR
75 # define SYSNDIR
76 #endif /* Xenix */
77
78 #if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__
79 # include <dirent.h>
80 # ifndef __GNU_LIBRARY__
81 # define D_NAMLEN(d) strlen((d)->d_name)
82 # else
83 # define HAVE_D_NAMLEN
84 # define D_NAMLEN(d) ((d)->d_namlen)
85 # endif
86 #else /* not POSIX or DIRENT */
87 # define dirent direct
88 # define D_NAMLEN(d) ((d)->d_namlen)
89 # define HAVE_D_NAMLEN
90 # if defined USG && !defined sgi
91 # if defined SYSNDIR
92 # include <sys/ndir.h>
93 # else /* Not SYSNDIR */
94 # include "ndir.h"
95 # endif /* SYSNDIR */
96 # else /* not USG */
97 # include <sys/dir.h>
98 # endif /* USG */
99 #endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
100
101 #if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__
102 # include <unistd.h>
103 #endif
104
105 #if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX
106 # include <stdlib.h>
107 # include <string.h>
108 # define ANSI_STRING
109 #else /* No standard headers. */
110
111 # ifdef USG
112
113 # include <string.h>
114 # ifdef NEED_MEMORY_H
115 # include <memory.h>
116 # endif
117 # define ANSI_STRING
118
119 # else /* Not USG. */
120
121 # ifdef NeXT
122
123 # include <string.h>
124
125 # else /* Not NeXT. */
126
127 # include <strings.h>
128
129 # ifndef bcmp
130 extern int bcmp();
131 # endif
132 # ifndef bzero
133 extern void bzero();
134 # endif
135 # ifndef bcopy
136 extern void bcopy();
137 # endif
138
139 # endif /* NeXT. */
140
141 # endif /* USG. */
142
143 extern char *malloc(), *realloc();
144 extern void free();
145
146 #endif /* Standard headers. */
147
148 #ifndef ANSI_STRING
149 # define memcpy(d, s, n) bcopy((s), (d), (n))
150 # define memmove memcpy
151 #endif /* Not ANSI_STRING. */
152
153 #ifndef MAX
154 # define MAX(a, b) ((a) < (b) ? (b) : (a))
155 #endif
156
157 #ifdef _LIBC
158 # ifndef mempcpy
159 # define mempcpy __mempcpy
160 # endif
161 # define HAVE_MEMPCPY 1
162 #endif
163
164 #if !defined __alloca && !defined __GNU_LIBRARY__
165
166 # ifdef __GNUC__
167 # undef alloca
168 # define alloca(n) __builtin_alloca (n)
169 # else /* Not GCC. */
170 # if defined sparc || defined HAVE_ALLOCA_H
171 # include <alloca.h>
172 # else /* Not sparc or HAVE_ALLOCA_H. */
173 # ifndef _AIX
174 extern char *alloca();
175 # endif /* Not _AIX. */
176 # endif /* sparc or HAVE_ALLOCA_H. */
177 # endif /* GCC. */
178
179 # define __alloca alloca
180
181 #endif
182
183 #if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__
184 # include <limits.h>
185 #else
186 # include <sys/param.h>
187 #endif
188
189 #ifndef PATH_MAX
190 # ifdef MAXPATHLEN
191 # define PATH_MAX MAXPATHLEN
192 # else
193 # define PATH_MAX 1024
194 # endif
195 #endif
196
197 #if !defined STDC_HEADERS && !defined __GNU_LIBRARY__
198 # undef size_t
199 # define size_t unsigned int
200 #endif
201
202 #if !__STDC__ && !defined const
203 # define const
204 #endif
205
206 #ifndef __GNU_LIBRARY__
207 # define __lstat stat
208 #endif
209
210 #ifndef _LIBC
211 # define __getcwd getcwd
212 #endif
213
214 #ifndef GETCWD_RETURN_TYPE
215 # define GETCWD_RETURN_TYPE char *
216 #endif
217
218 #ifndef SB_PATH_MAX
219 # include "localdecls.h"
220 # define OUTSIDE_LIBSANDBOX
221 #endif
222
223 #ifndef __LIBC
224 # define __lstat lstat
225 # define __readdir readdir
226 # define __closedir closedir
227 #endif
228
229 /* Get the pathname of the current working directory, and put it in SIZE
230 bytes of BUF. Returns NULL if the directory couldn't be determined or
231 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
232 NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
233 unless SIZE == 0, in which case it is as big as necessary. */
234
235 GETCWD_RETURN_TYPE
236 __egetcwd(buf, size)
237 char *buf;
238 size_t size;
239 {
240 static const char dots[]
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 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
281 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
282 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
283 const char *dotp = &dots[sizeof (dots)];
284 const char *dotlist = dots;
285 size_t dotsize = sizeof (dots) - 1;
286 dev_t rootdev, thisdev;
287 ino_t rootino, thisino;
288 char *path;
289 register char *pathp;
290 struct stat st;
291 int prev_errno = errno;
292 size_t allocated = size;
293
294 if (size == 0) {
295 if (buf != NULL) {
296 __set_errno(EINVAL);
297 return NULL;
298 }
299
300 allocated = SB_PATH_MAX + 1;
301 }
302
303 if (buf != NULL)
304 path = buf;
305 else {
306 path = malloc(allocated);
307 if (path == NULL)
308 return NULL;
309 }
310
311 pathp = path + allocated;
312 *--pathp = '\0';
313
314 if (__lstat(".", &st) < 0)
315 goto lose2;
316 thisdev = st.st_dev;
317 thisino = st.st_ino;
318
319 if (__lstat("/", &st) < 0)
320 goto lose2;
321 rootdev = st.st_dev;
322 rootino = st.st_ino;
323
324 while (!(thisdev == rootdev && thisino == rootino)) {
325 register DIR *dirstream;
326 struct dirent *d;
327 dev_t dotdev;
328 ino_t dotino;
329 char mount_point;
330
331 /* Look at the parent directory. */
332 if (dotp == dotlist) {
333 /* My, what a deep directory tree you have, Grandma. */
334 char *new;
335 if (dotlist == dots) {
336 new = malloc(dotsize * 2 + 1);
337 if (new == NULL)
338 goto lose;
339 #ifdef HAVE_MEMPCPY
340 dotp = mempcpy(new, dots, dotsize);
341 #else
342 memcpy(new, dots, dotsize);
343 dotp = &new[dotsize];
344 #endif
345 } else {
346 new = realloc((__ptr_t) dotlist, dotsize * 2 + 1);
347 if (new == NULL)
348 goto lose;
349 dotp = &new[dotsize];
350 }
351 #ifdef HAVE_MEMPCPY
352 *((char *) mempcpy((char *) dotp, new, dotsize)) = '\0';
353 dotsize *= 2;
354 #else
355 memcpy((char *) dotp, new, dotsize);
356 dotsize *= 2;
357 new[dotsize] = '\0';
358 #endif
359 dotlist = new;
360 }
361
362 dotp -= 3;
363
364 /* Figure out if this directory is a mount point. */
365 if (__lstat(dotp, &st) < 0)
366 goto lose;
367 dotdev = st.st_dev;
368 dotino = st.st_ino;
369 mount_point = dotdev != thisdev;
370
371 /* Search for the last directory. */
372 #ifdef OUTSIDE_LIBSANDBOX
373 dirstream = opendir(dotp);
374 #else
375 dirstream = true_opendir(dotp);
376 #endif
377 if (dirstream == NULL)
378 goto lose;
379 /* Clear errno to distinguish EOF from error if readdir returns
380 NULL. */
381 __set_errno(0);
382 while ((d = __readdir(dirstream)) != NULL) {
383 if (d->d_name[0] == '.' &&
384 (d->d_name[1] == '\0'
385 || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
386 continue;
387 if (mount_point || (ino_t) d->d_ino == thisino) {
388 char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN(d)];
389 #ifdef HAVE_MEMPCPY
390 char *tmp = mempcpy(name, dotp,
391 dotlist + dotsize - dotp);
392 *tmp++ = '/';
393 strcpy(tmp, d->d_name);
394 #else
395 memcpy(name, dotp, dotlist + dotsize - dotp);
396 name[dotlist + dotsize - dotp] = '/';
397 strcpy(&name[dotlist + dotsize - dotp + 1], d->d_name);
398 #endif
399 /* We don't fail here if we cannot stat() a directory entry.
400 This can happen when (network) filesystems fail. If this
401 entry is in fact the one we are looking for we will find
402 out soon as we reach the end of the directory without
403 having found anything. */
404 if (__lstat(name, &st) >= 0 && st.st_dev == thisdev
405 && st.st_ino == thisino)
406 break;
407 }
408 }
409 if (d == NULL) {
410 int save = errno;
411 (void) __closedir(dirstream);
412 if (save == 0)
413 /* EOF on dirstream, which means that the current directory
414 has been removed. */
415 save = ENOENT;
416 __set_errno(save);
417 goto lose;
418 } else {
419 size_t namlen = _D_EXACT_NAMLEN(d);
420
421 if ((size_t) (pathp - path) <= namlen) {
422 if (size != 0) {
423 (void) __closedir(dirstream);
424 __set_errno(ERANGE);
425 goto lose;
426 } else {
427 char *tmp;
428 size_t oldsize = allocated;
429
430 allocated = 2 * MAX(allocated, namlen);
431 tmp = realloc(path, allocated);
432 if (tmp == NULL) {
433 (void) __closedir(dirstream);
434 __set_errno(ENOMEM); /* closedir might have changed it. */
435 goto lose;
436 }
437
438 /* Move current contents up to the end of the buffer.
439 This is guaranteed to be non-overlapping. */
440 pathp =
441 memcpy(tmp + allocated -
442 (path + oldsize - pathp),
443 tmp + (pathp - path), path + oldsize - pathp);
444 path = tmp;
445 }
446 }
447 pathp -= namlen;
448 (void) memcpy(pathp, d->d_name, namlen);
449 *--pathp = '/';
450 (void) __closedir(dirstream);
451 }
452
453 thisdev = dotdev;
454 thisino = dotino;
455 }
456
457 if (pathp == &path[allocated - 1])
458 *--pathp = '/';
459
460 if (dotlist != dots)
461 free((__ptr_t) dotlist);
462
463 memmove(path, pathp, path + allocated - pathp);
464
465 /* Restore errno on successful return. */
466 __set_errno(prev_errno);
467
468 return path;
469
470 lose:
471 if (dotlist != dots)
472 free((__ptr_t) dotlist);
473 lose2:
474 if (buf == NULL)
475 free(path);
476 return NULL;
477 }
478
479 GETCWD_RETURN_TYPE
480 egetcwd(buf, size)
481 char *buf;
482 size_t size;
483 {
484 struct stat st;
485 char *tmpbuf;
486
487 __set_errno(0);
488 tmpbuf = getcwd(buf, size);
489
490 if (tmpbuf) {
491 __lstat(buf, &st);
492 } else {
493 return tmpbuf;
494 }
495
496 if (errno) {
497 /* If lstat() failed with eerror = ENOENT, then its
498 * possible that we are running on an older kernel,
499 * so use our generic version which *should* not fail.
500 */
501 if (errno == ENOENT) {
502 return __egetcwd(buf, size);
503 } else {
504 return tmpbuf;
505 }
506 }
507
508 return tmpbuf;
509 }
510
511 // vim:expandtab noai:cindent ai

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20