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

Contents of /trunk/getcwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 111 - (show annotations) (download) (as text)
Thu Jun 9 15:12:20 2005 UTC (9 years, 3 months ago) by azarah
File MIME type: text/x-csrc
File size: 4423 byte(s)
Use generic getcwd() implementation from uclibc - should be more portable
and looks a bit cleaner.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20