/[path-sandbox]/tags/sandbox_1_2_10/getcwd.c
Gentoo

Contents of /tags/sandbox_1_2_10/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 130 - (hide annotations) (download) (as text)
Sun Jul 3 18:52:38 2005 UTC (12 years, 10 months ago) by azarah
File MIME type: text/x-csrc
File size: 4488 byte(s)
Add tag tags/sandbox_1_2_10.
1 azarah 111 /* These functions find the absolute path to the current working directory. */
2 ferringb 2
3 azarah 117 #include <stdio.h>
4 azarah 111 #include <stdlib.h>
5 ferringb 2 #include <errno.h>
6     #include <sys/types.h>
7     #include <sys/stat.h>
8 azarah 111 #include <dirent.h>
9     #include <unistd.h>
10     #include <string.h>
11 ferringb 2
12 ferringb 25 #include "config.h"
13     #include <sys/param.h>
14 ferringb 26 #include "localdecls.h"
15 ferringb 25
16 azarah 111 /* Modified: 08 June 2005; Martin Schlemmer <azarah@gentoo.org>
17     *
18     * Cleaned up unneeded stuff. Add a wrapper to try and detect when
19     * we have a kernel whose getcwd system call do not handle directory
20     * names longer than PATH_MAX, and if so, use our generic version.
21     */
22 ferringb 25
23 ferringb 2 #ifndef __set_errno
24     # define __set_errno(val) errno = (val)
25     #endif
26    
27 azarah 111 /* If the syscall is not present, we have to walk up the
28     * directory tree till we hit the root. Now we _could_
29     * use /proc/self/cwd if /proc is mounted... That approach
30     * is left an an exercise for the reader... */
31 ferringb 2
32    
33 azarah 111 /* Seems a few broken filesystems (like coda) don't like this */
34     /*#undef FAST_DIR_SEARCH_POSSIBLE on Linux */
35 ferringb 2
36    
37 azarah 111 /* Routine to find the step back down */
38     SB_STATIC char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, size_t path_size)
39     {
40     DIR *dp;
41     struct dirent *d;
42     char *ptr;
43     size_t slen;
44     struct stat st;
45 ferringb 2
46 azarah 111 #ifdef FAST_DIR_SEARCH_POSSIBLE
47     /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */
48     size_t slow_search = (sizeof(ino_t) != sizeof(d->d_ino));
49 ferringb 2 #endif
50    
51 azarah 111 // if (stat(path_buf, &st) < 0) {
52     // goto oops;
53     // }
54     #ifdef FAST_DIR_SEARCH_POSSIBLE
55     if (this_dev != st.st_dev)
56     slow_search = 1;
57 ferringb 2 #endif
58    
59 azarah 111 slen = strlen(path_buf);
60     ptr = path_buf + slen - 1;
61     if (*ptr != '/') {
62     if (slen + 2 > path_size) {
63     goto oops;
64     }
65 azarah 117 snprintf(++ptr, 2, "/");
66 azarah 111 slen++;
67     }
68     slen++;
69 ferringb 2
70 azarah 111 #ifdef OUTSIDE_LIBSANDBOX
71     dp = opendir(path_buf);
72 ferringb 2 #else
73 azarah 111 check_dlsym(opendir);
74     dp = true_opendir(path_buf);
75 ferringb 2 #endif
76 azarah 111 if (dp == 0) {
77     goto oops;
78     }
79 ferringb 2
80 azarah 111 while ((d = readdir(dp)) != 0) {
81     #ifdef FAST_DIR_SEARCH_POSSIBLE
82     if (slow_search || this_ino == d->d_ino) {
83 ferringb 2 #endif
84 azarah 111 if (slen + strlen(d->d_name) > path_size) {
85     goto oops;
86     }
87 azarah 117 snprintf(ptr + 1, sizeof(d->d_name) + 1, "%s", d->d_name);
88 azarah 111 if (lstat(path_buf, &st) < 0)
89     continue;
90     if (st.st_ino == this_ino && st.st_dev == this_dev) {
91     closedir(dp);
92     return path_buf;
93     }
94     #ifdef FAST_DIR_SEARCH_POSSIBLE
95     }
96 ferringb 2 #endif
97 azarah 111 }
98 ferringb 2
99 azarah 111 closedir(dp);
100     return 0;
101 ferringb 2
102 azarah 111 oops:
103     __set_errno(ERANGE);
104     return 0;
105     }
106 ferringb 2
107 azarah 111 /* Routine to go up tree */
108     SB_STATIC char *recurser(char *path_buf, size_t path_size, dev_t root_dev, ino_t root_ino)
109 ferringb 2 {
110     struct stat st;
111 azarah 111 dev_t this_dev;
112     ino_t this_ino;
113 ferringb 2
114 azarah 111 if (lstat(path_buf, &st) < 0) {
115     if (errno != EFAULT)
116     goto oops;
117     return 0;
118     }
119     this_dev = st.st_dev;
120     this_ino = st.st_ino;
121     if (this_dev == root_dev && this_ino == root_ino) {
122     if (path_size < 2) {
123     goto oops;
124 ferringb 2 }
125 azarah 117 snprintf(path_buf, 2, "/");
126 azarah 111 return path_buf;
127 ferringb 2 }
128 azarah 111 if (strlen(path_buf) + 4 > path_size) {
129     goto oops;
130 ferringb 2 }
131 azarah 117 snprintf(path_buf, 4, "/..");
132 azarah 111 if (recurser(path_buf, path_size, root_dev, root_ino) == 0)
133     return 0;
134 ferringb 2
135 azarah 111 return search_dir(this_dev, this_ino, path_buf, path_size);
136     oops:
137     __set_errno(ERANGE);
138     return 0;
139     }
140 ferringb 2
141 azarah 111 SB_STATIC inline
142     size_t __syscall_egetcwd(char * buf, unsigned long size)
143     {
144     size_t len;
145     char *cwd;
146     struct stat st;
147     size_t olderrno;
148 ferringb 2
149 azarah 111 olderrno = errno;
150     len = -1;
151     cwd = recurser(buf, size, st.st_dev, st.st_ino);
152     if (cwd) {
153     len = strlen(buf);
154     __set_errno(olderrno);
155     }
156     return len;
157     }
158 ferringb 2
159 azarah 111 SB_STATIC char *__egetcwd(char *buf, size_t size)
160     {
161     size_t ret;
162     char *path;
163     size_t alloc_size = size;
164 ferringb 2
165 azarah 111 if (size == 0) {
166     if (buf != NULL) {
167     __set_errno(EINVAL);
168     return NULL;
169 ferringb 2 }
170 azarah 111 alloc_size = SB_PATH_MAX;
171     }
172     path=buf;
173     if (buf == NULL) {
174     path = malloc(alloc_size);
175     if (path == NULL)
176     return NULL;
177     }
178     ret = __syscall_egetcwd(path, alloc_size);
179     if (ret >= 0)
180     {
181     if (buf == NULL && size == 0)
182     buf = realloc(path, ret);
183 ferringb 2 if (buf == NULL)
184 azarah 111 buf = path;
185     return buf;
186     }
187     if (buf == NULL)
188     free (path);
189     return NULL;
190 ferringb 2 }
191    
192 azarah 111 SB_STATIC char *egetcwd(char *buf, size_t size)
193 ferringb 2 {
194     struct stat st;
195     char *tmpbuf;
196    
197     __set_errno(0);
198     tmpbuf = getcwd(buf, size);
199    
200     if (tmpbuf) {
201 azarah 111 lstat(buf, &st);
202 ferringb 2 } else {
203     return tmpbuf;
204     }
205    
206     if (errno) {
207     /* If lstat() failed with eerror = ENOENT, then its
208     * possible that we are running on an older kernel,
209     * so use our generic version which *should* not fail.
210     */
211     if (errno == ENOENT) {
212     return __egetcwd(buf, size);
213     } else {
214     return tmpbuf;
215     }
216     }
217    
218     return tmpbuf;
219     }
220    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20