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