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

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 ferringb 2 /* 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 azarah 30 * Cleaned up unneeded stuff. Add a wrapper to try and detect when
35 ferringb 2 * 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 ferringb 25 #include "config.h"
58     #include <sys/param.h>
59 ferringb 26 #include "localdecls.h"
60 ferringb 25
61    
62 ferringb 2 #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 azarah 30 #ifndef NULL
70 ferringb 2 # define NULL 0
71     #endif
72    
73     #if defined USGr3 && !defined DIRENT
74     # define DIRENT
75 azarah 30 #endif /* USGr3 */
76 ferringb 2 #if defined Xenix && !defined SYSNDIR
77     # define SYSNDIR
78 azarah 30 #endif /* Xenix */
79 ferringb 2
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 azarah 30 #else /* not POSIX or DIRENT */
89 ferringb 2 # 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 azarah 30 # else /* Not SYSNDIR */
96 ferringb 2 # include "ndir.h"
97 azarah 30 # endif /* SYSNDIR */
98     # else /* not USG */
99 ferringb 2 # include <sys/dir.h>
100 azarah 30 # endif /* USG */
101     #endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
102 ferringb 2
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 azarah 30 #else /* No standard headers. */
112 ferringb 2
113 azarah 30 # ifdef USG
114 ferringb 2
115     # include <string.h>
116     # ifdef NEED_MEMORY_H
117     # include <memory.h>
118     # endif
119     # define ANSI_STRING
120    
121 azarah 30 # else /* Not USG. */
122 ferringb 2
123     # ifdef NeXT
124    
125     # include <string.h>
126    
127 azarah 30 # else /* Not NeXT. */
128 ferringb 2
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 azarah 30 # endif /* NeXT. */
142 ferringb 2
143 azarah 30 # endif /* USG. */
144 ferringb 2
145     extern char *malloc(), *realloc();
146     extern void free();
147    
148 azarah 30 #endif /* Standard headers. */
149 ferringb 2
150 azarah 30 #ifndef ANSI_STRING
151 ferringb 2 # define memcpy(d, s, n) bcopy((s), (d), (n))
152     # define memmove memcpy
153 azarah 30 #endif /* Not ANSI_STRING. */
154 ferringb 2
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 azarah 30 # ifdef __GNUC__
169 ferringb 2 # undef alloca
170     # define alloca(n) __builtin_alloca (n)
171 azarah 30 # else /* Not GCC. */
172 ferringb 2 # if defined sparc || defined HAVE_ALLOCA_H
173     # include <alloca.h>
174 azarah 30 # else /* Not sparc or HAVE_ALLOCA_H. */
175 ferringb 2 # ifndef _AIX
176     extern char *alloca();
177 azarah 30 # endif /* Not _AIX. */
178     # endif /* sparc or HAVE_ALLOCA_H. */
179     # endif /* GCC. */
180 ferringb 2
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 azarah 30 # ifdef MAXPATHLEN
193 ferringb 2 # 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 azarah 30 # undef size_t
201     # define size_t unsigned int
202 ferringb 2 #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 azarah 30 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
229 ferringb 2 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 azarah 29 dotp = (char *)mempcpy(new, dots, dotsize);
338 ferringb 2 #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 azarah 30 dotlist + dotsize - dotp);
389 ferringb 2 *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 azarah 30 pathp = memcpy(tmp + allocated -
438     (path + oldsize - pathp),
439     tmp + (pathp - path), path + oldsize - pathp);
440 ferringb 2 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 azarah 30 /* Restore errno on successful return. */
462 ferringb 2 __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 azarah 30 // 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