This source file includes following definitions.
- fdopendir
- fdopendir
- fdopendir
- fdopendir_with_dup
- fd_clone_opendir
- rpl_fdopendir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #include <dirent.h>
22
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 #if !HAVE_FDOPENDIR
27
28 # if GNULIB_defined_DIR
29
30
31 # include "dirent-private.h"
32
33 # if !REPLACE_FCHDIR
34 # error "unexpected configuration: GNULIB_defined_DIR but fchdir not replaced"
35 # endif
36
37 DIR *
38 fdopendir (int fd)
39 {
40 char const *name = _gl_directory_name (fd);
41 DIR *dirp = name ? opendir (name) : NULL;
42 if (dirp != NULL)
43 dirp->fd_to_close = fd;
44 return dirp;
45 }
46
47 # elif defined __KLIBC__
48
49 # include <InnoTekLIBC/backend.h>
50
51 DIR *
52 fdopendir (int fd)
53 {
54 char path[_MAX_PATH];
55 DIR *dirp;
56
57
58 if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
59 return NULL;
60
61 dirp = opendir (path);
62 if (!dirp)
63 return NULL;
64
65
66 _gl_unregister_dirp_fd (dirfd (dirp));
67
68
69 if (_gl_register_dirp_fd (fd, dirp))
70 {
71 int saved_errno = errno;
72
73 closedir (dirp);
74
75 errno = saved_errno;
76
77 dirp = NULL;
78 }
79
80 return dirp;
81 }
82
83 # else
84
85
86
87 # include "openat.h"
88 # include "openat-priv.h"
89 # include "save-cwd.h"
90
91 # if GNULIB_DIRENT_SAFER
92 # include "dirent--.h"
93 # endif
94
95 # ifndef REPLACE_FCHDIR
96 # define REPLACE_FCHDIR 0
97 # endif
98
99 static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *);
100 static DIR *fd_clone_opendir (int, struct saved_cwd const *);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 DIR *
125 fdopendir (int fd)
126 {
127 DIR *dir = fdopendir_with_dup (fd, -1, NULL);
128
129 if (! REPLACE_FCHDIR && ! dir)
130 {
131 int saved_errno = errno;
132 if (EXPECTED_ERRNO (saved_errno))
133 {
134 struct saved_cwd cwd;
135 if (save_cwd (&cwd) != 0)
136 openat_save_fail (errno);
137 dir = fdopendir_with_dup (fd, -1, &cwd);
138 saved_errno = errno;
139 free_cwd (&cwd);
140 errno = saved_errno;
141 }
142 }
143
144 return dir;
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158 static DIR *
159 fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd)
160 {
161 int dupfd = dup (fd);
162 if (dupfd < 0 && errno == EMFILE)
163 dupfd = older_dupfd;
164 if (dupfd < 0)
165 return NULL;
166 else
167 {
168 DIR *dir;
169 int saved_errno;
170 if (dupfd < fd - 1 && dupfd != older_dupfd)
171 {
172 dir = fdopendir_with_dup (fd, dupfd, cwd);
173 saved_errno = errno;
174 }
175 else
176 {
177 close (fd);
178 dir = fd_clone_opendir (dupfd, cwd);
179 saved_errno = errno;
180 if (! dir)
181 {
182 int fd1 = dup (dupfd);
183 if (fd1 != fd)
184 openat_save_fail (fd1 < 0 ? errno : EBADF);
185 }
186 }
187
188 if (dupfd != older_dupfd)
189 close (dupfd);
190 errno = saved_errno;
191 return dir;
192 }
193 }
194
195
196
197
198 static DIR *
199 fd_clone_opendir (int fd, struct saved_cwd const *cwd)
200 {
201 if (REPLACE_FCHDIR || ! cwd)
202 {
203 DIR *dir = NULL;
204 int saved_errno = EOPNOTSUPP;
205 char buf[OPENAT_BUFFER_SIZE];
206 char *proc_file = openat_proc_name (buf, fd, ".");
207 if (proc_file)
208 {
209 dir = opendir (proc_file);
210 saved_errno = errno;
211 if (proc_file != buf)
212 free (proc_file);
213 }
214 # if REPLACE_FCHDIR
215 if (! dir && EXPECTED_ERRNO (saved_errno))
216 {
217 char const *name = _gl_directory_name (fd);
218 DIR *dp = name ? opendir (name) : NULL;
219
220
221
222
223
224 if (dp && dirfd (dp) < 0)
225 dup (fd);
226
227 return dp;
228 }
229 # endif
230 errno = saved_errno;
231 return dir;
232 }
233 else
234 {
235 if (fchdir (fd) != 0)
236 return NULL;
237 else
238 {
239 DIR *dir = opendir (".");
240 int saved_errno = errno;
241 if (restore_cwd (cwd) != 0)
242 openat_restore_fail (errno);
243 errno = saved_errno;
244 return dir;
245 }
246 }
247 }
248
249 # endif
250
251 #else
252
253 # include <errno.h>
254 # include <sys/stat.h>
255
256 # undef fdopendir
257
258
259
260 DIR *
261 rpl_fdopendir (int fd)
262 {
263 struct stat st;
264 if (fstat (fd, &st))
265 return NULL;
266 if (!S_ISDIR (st.st_mode))
267 {
268 errno = ENOTDIR;
269 return NULL;
270 }
271 return fdopendir (fd);
272 }
273
274 #endif