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

Contents of /tags/sandbox_1_2_13/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 168 - (show annotations) (download) (as text)
Mon Sep 12 07:10:27 2005 UTC (9 years, 2 months ago) by azarah
File MIME type: text/x-csrc
File size: 4566 byte(s)
Add sandbox_1_2_13 tag.
1 /* These functions find the absolute path to the current working directory. */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <dirent.h>
9 #include <unistd.h>
10 #include <string.h>
11
12 #include "config.h"
13 #include <sys/param.h>
14 #include "localdecls.h"
15
16 /* 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
23 #ifndef __set_errno
24 # define __set_errno(val) errno = (val)
25 #endif
26
27 /* 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
32
33 /* Seems a few broken filesystems (like coda) don't like this */
34 /*#undef FAST_DIR_SEARCH_POSSIBLE on Linux */
35
36
37 /* 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
46 #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 #endif
50
51 // 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 #endif
58
59 slen = strlen(path_buf);
60 ptr = path_buf + slen - 1;
61 if (*ptr != '/') {
62 if (slen + 2 > path_size) {
63 goto oops;
64 }
65 snprintf(++ptr, 2, "/");
66 slen++;
67 }
68 slen++;
69
70 #ifdef OUTSIDE_LIBSANDBOX
71 dp = opendir(path_buf);
72 #else
73 check_dlsym(opendir);
74 dp = true_opendir(path_buf);
75 #endif
76 if (dp == 0) {
77 goto oops;
78 }
79
80 while ((d = readdir(dp)) != 0) {
81 #ifdef FAST_DIR_SEARCH_POSSIBLE
82 if (slow_search || this_ino == d->d_ino) {
83 #endif
84 if (slen + strlen(d->d_name) > path_size) {
85 goto oops;
86 }
87 snprintf(ptr + 1, sizeof(d->d_name) + 1, "%s", d->d_name);
88 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 #endif
97 }
98
99 closedir(dp);
100 return 0;
101
102 oops:
103 __set_errno(ERANGE);
104 return 0;
105 }
106
107 /* 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 {
110 struct stat st;
111 dev_t this_dev;
112 ino_t this_ino;
113
114 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 }
125 snprintf(path_buf, 2, "/");
126 return path_buf;
127 }
128 if (strlen(path_buf) + 4 > path_size) {
129 goto oops;
130 }
131 snprintf(path_buf + strlen(path_buf), 4, "/..");
132 if (recurser(path_buf, path_size, root_dev, root_ino) == 0)
133 return 0;
134
135 return search_dir(this_dev, this_ino, path_buf, path_size);
136 oops:
137 __set_errno(ERANGE);
138 return 0;
139 }
140
141 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
149 if (lstat("/", &st) < 0)
150 return -1;
151 olderrno = errno;
152 len = -1;
153 cwd = recurser(buf, size, st.st_dev, st.st_ino);
154 if (cwd) {
155 len = strlen(buf);
156 __set_errno(olderrno);
157 }
158 return len;
159 }
160
161 SB_STATIC char *__egetcwd(char *buf, size_t size)
162 {
163 size_t ret;
164 char *path;
165 size_t alloc_size = size;
166
167 if (size == 0) {
168 if (buf != NULL) {
169 __set_errno(EINVAL);
170 return NULL;
171 }
172 alloc_size = SB_PATH_MAX;
173 }
174 path=buf;
175 if (buf == NULL) {
176 path = malloc(alloc_size);
177 if (path == NULL)
178 return NULL;
179 }
180 snprintf(buf, 2, ".");
181 ret = __syscall_egetcwd(path, alloc_size);
182 if (ret >= 0)
183 {
184 if (buf == NULL && size == 0)
185 buf = realloc(path, ret);
186 if (buf == NULL)
187 buf = path;
188 return buf;
189 }
190 if (buf == NULL)
191 free (path);
192 return NULL;
193 }
194
195 SB_STATIC char *egetcwd(char *buf, size_t size)
196 {
197 struct stat st;
198 char *tmpbuf;
199
200 __set_errno(0);
201 tmpbuf = getcwd(buf, size);
202
203 if (tmpbuf)
204 lstat(buf, &st);
205 else
206 return tmpbuf;
207
208 if (errno) {
209 /* If lstat() failed with eerror = ENOENT, then its
210 * possible that we are running on an older kernel,
211 * so use our generic version which *should* not fail.
212 */
213 if (errno == ENOENT) {
214 return __egetcwd(buf, size);
215 } else {
216 return tmpbuf;
217 }
218 }
219
220 return tmpbuf;
221 }

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20