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

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations) (download) (as text)
Sun Dec 5 06:14:21 2004 UTC (13 years, 7 months ago) by ferringb
File MIME type: text/x-csrc
File size: 13995 byte(s)
compilation fixups.

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     * 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 ferringb 25 #include "config.h"
58     #include <sys/param.h>
59     #include "sb_path_max.h"
60    
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     #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