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

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations) (download) (as text)
Mon Dec 6 21:42:51 2004 UTC (9 years, 9 months ago) by ferringb
File MIME type: text/x-csrc
File size: 13994 byte(s)
hopefully cvs is done being stupid.  Compilation fixes, along w/ make dist fix.

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 = 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 =
438 memcpy(tmp + allocated -
439 (path + oldsize - pathp),
440 tmp + (pathp - path), path + oldsize - pathp);
441 path = tmp;
442 }
443 }
444 pathp -= namlen;
445 (void) memcpy(pathp, d->d_name, namlen);
446 *--pathp = '/';
447 (void) __closedir(dirstream);
448 }
449
450 thisdev = dotdev;
451 thisino = dotino;
452 }
453
454 if (pathp == &path[allocated - 1])
455 *--pathp = '/';
456
457 if (dotlist != dots)
458 free((__ptr_t) dotlist);
459
460 memmove(path, pathp, path + allocated - pathp);
461
462 /* Restore errno on successful return. */
463 __set_errno(prev_errno);
464
465 return path;
466
467 lose:
468 if (dotlist != dots)
469 free((__ptr_t) dotlist);
470 lose2:
471 if (buf == NULL)
472 free(path);
473 return NULL;
474 }
475
476 GETCWD_RETURN_TYPE
477 egetcwd(buf, size)
478 char *buf;
479 size_t size;
480 {
481 struct stat st;
482 char *tmpbuf;
483
484 __set_errno(0);
485 tmpbuf = getcwd(buf, size);
486
487 if (tmpbuf) {
488 __lstat(buf, &st);
489 } else {
490 return tmpbuf;
491 }
492
493 if (errno) {
494 /* If lstat() failed with eerror = ENOENT, then its
495 * possible that we are running on an older kernel,
496 * so use our generic version which *should* not fail.
497 */
498 if (errno == ENOENT) {
499 return __egetcwd(buf, size);
500 } else {
501 return tmpbuf;
502 }
503 }
504
505 return tmpbuf;
506 }
507
508 // 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