]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/dir.cc
Remove unneeded header files from source files throughout.
[newlib-cygwin.git] / winsup / cygwin / dir.cc
1 /* dir.cc: Posix directory-related routines
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include <stdlib.h>
13
14 #define _COMPILING_NEWLIB
15 #include <dirent.h>
16
17 #include "cygerrno.h"
18 #include "security.h"
19 #include "path.h"
20 #include "fhandler.h"
21 #include "dtable.h"
22 #include "cygheap.h"
23 #include "cygtls.h"
24
25 extern "C" int
26 dirfd (DIR *dir)
27 {
28 myfault efault;
29 if (efault.faulted (EFAULT))
30 return -1;
31 if (dir->__d_cookie != __DIRENT_COOKIE)
32 {
33 set_errno (EBADF);
34 syscall_printf ("-1 = dirfd (%p)", dir);
35 return -1;
36 }
37 return dir->__d_fd;
38 }
39
40 /* Symbol kept for backward compatibility. Don't remove. Don't declare
41 in public header file. */
42 extern "C" DIR *
43 __opendir_with_d_ino (const char *name)
44 {
45 return opendir (name);
46 }
47
48 /* opendir: POSIX 5.1.2.1 */
49 extern "C" DIR *
50 opendir (const char *name)
51 {
52 fhandler_base *fh;
53 DIR *res;
54
55 fh = build_fh_name (name, NULL, PC_SYM_FOLLOW);
56 if (!fh)
57 res = NULL;
58 else if (fh->exists ())
59 res = fh->opendir (-1);
60 else
61 {
62 set_errno (ENOENT);
63 res = NULL;
64 }
65
66 if (!res && fh)
67 delete fh;
68 return res;
69 }
70
71 extern "C" DIR *
72 fdopendir (int fd)
73 {
74 DIR *res = NULL;
75
76 cygheap_fdget cfd (fd);
77 if (cfd >= 0)
78 res = cfd->opendir (fd);
79 return res;
80 }
81
82 static int
83 readdir_worker (DIR *dir, dirent *de)
84 {
85 myfault efault;
86 if (efault.faulted ())
87 return EFAULT;
88
89 if (dir->__d_cookie != __DIRENT_COOKIE)
90 {
91 syscall_printf ("%p = readdir (%p)", NULL, dir);
92 return EBADF;
93 }
94
95 de->d_ino = 0;
96 int res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
97
98 if (res == ENMFILE)
99 {
100 if (!(dir->__flags & dirent_saw_dot))
101 {
102 strcpy (de->d_name, ".");
103 dir->__flags |= dirent_saw_dot;
104 dir->__d_position++;
105 res = 0;
106 }
107 else if (!(dir->__flags & dirent_saw_dot_dot))
108 {
109 strcpy (de->d_name, "..");
110 dir->__flags |= dirent_saw_dot_dot;
111 dir->__d_position++;
112 res = 0;
113 }
114 }
115
116 if (!res && !de->d_ino)
117 {
118 bool is_dot = false;
119 bool is_dot_dot = false;
120
121 if (de->d_name[0] == '.')
122 {
123 if (de->d_name[1] == '\0')
124 is_dot = true;
125 else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
126 is_dot_dot = true;
127 }
128
129 if (is_dot_dot && !(dir->__flags & dirent_isroot))
130 de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (),
131 true);
132 else
133 {
134 /* Compute d_ino by combining filename hash with directory hash. */
135 de->d_ino = ((fhandler_base *) dir->__fh)->get_ino ();
136 if (!is_dot && !is_dot_dot)
137 {
138 PUNICODE_STRING w32name =
139 ((fhandler_base *) dir->__fh)->pc.get_nt_native_path ();
140 DWORD devn = ((fhandler_base *) dir->__fh)->get_device ();
141 /* Paths below /proc don't have a Win32 pendant. */
142 if (isproc_dev (devn))
143 de->d_ino = hash_path_name (de->d_ino, L"/");
144 else if (w32name->Buffer[w32name->Length / sizeof (WCHAR) - 1]
145 != L'\\')
146 de->d_ino = hash_path_name (de->d_ino, L"\\");
147 de->d_ino = hash_path_name (de->d_ino, de->d_name);
148 }
149 }
150 }
151 /* This fills out the old 32 bit d_ino field for old applications,
152 build under Cygwin before 1.5.x. */
153 de->__d_internal1 = de->d_ino;
154
155 return res;
156 }
157
158 /* readdir: POSIX 5.1.2.1 */
159 extern "C" struct dirent *
160 readdir (DIR *dir)
161 {
162 int res = readdir_worker (dir, dir->__d_dirent);
163 if (res == 0)
164 return dir->__d_dirent;
165 if (res != ENMFILE)
166 set_errno (res);
167 return NULL;
168 }
169
170 extern "C" int
171 readdir_r (DIR *dir, dirent *de, dirent **ode)
172 {
173 int res = readdir_worker (dir, de);
174 if (!res)
175 *ode = de;
176 else
177 {
178 *ode = NULL;
179 if (res == ENMFILE)
180 res = 0;
181 }
182 return res;
183 }
184
185 extern "C" _off64_t
186 telldir64 (DIR *dir)
187 {
188 myfault efault;
189 if (efault.faulted (EFAULT))
190 return -1;
191
192 if (dir->__d_cookie != __DIRENT_COOKIE)
193 return 0;
194 return ((fhandler_base *) dir->__fh)->telldir (dir);
195 }
196
197 /* telldir */
198 extern "C" _off_t
199 telldir (DIR *dir)
200 {
201 return telldir64 (dir);
202 }
203
204 extern "C" void
205 seekdir64 (DIR *dir, _off64_t loc)
206 {
207 myfault efault;
208 if (efault.faulted (EFAULT))
209 return;
210
211 if (dir->__d_cookie != __DIRENT_COOKIE)
212 return;
213 dir->__flags &= dirent_info_mask;
214 return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
215 }
216
217 /* seekdir */
218 extern "C" void
219 seekdir (DIR *dir, _off_t loc)
220 {
221 seekdir64 (dir, (_off64_t)loc);
222 }
223
224 /* rewinddir: POSIX 5.1.2.1 */
225 extern "C" void
226 rewinddir (DIR *dir)
227 {
228 myfault efault;
229 if (efault.faulted (EFAULT))
230 return;
231
232 if (dir->__d_cookie != __DIRENT_COOKIE)
233 return;
234 dir->__flags &= dirent_info_mask;
235 return ((fhandler_base *) dir->__fh)->rewinddir (dir);
236 }
237
238 /* closedir: POSIX 5.1.2.1 */
239 extern "C" int
240 closedir (DIR *dir)
241 {
242 myfault efault;
243 if (efault.faulted (EFAULT))
244 return -1;
245
246 if (dir->__d_cookie != __DIRENT_COOKIE)
247 {
248 set_errno (EBADF);
249 syscall_printf ("-1 = closedir (%p)", dir);
250 return -1;
251 }
252
253 /* Reset the marker in case the caller tries to use `dir' again. */
254 dir->__d_cookie = 0;
255
256 int res = ((fhandler_base *) dir->__fh)->closedir (dir);
257
258 cygheap->fdtab.release (dir->__d_fd);
259
260 free (dir->__d_dirname);
261 free (dir->__d_dirent);
262 free (dir);
263 syscall_printf ("%d = closedir (%p)", res);
264 return res;
265 }
266
267 /* mkdir: POSIX 5.4.1.1 */
268 extern "C" int
269 mkdir (const char *dir, mode_t mode)
270 {
271 int res = -1;
272 fhandler_base *fh = NULL;
273
274 myfault efault;
275 if (efault.faulted (EFAULT))
276 return -1;
277
278 if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW)))
279 goto done; /* errno already set */;
280
281 if (fh->error ())
282 {
283 debug_printf ("got %d error from build_fh_name", fh->error ());
284 set_errno (fh->error ());
285 }
286 else if (has_dot_last_component (dir, true))
287 set_errno (fh->exists () ? EEXIST : ENOENT);
288 else if (!fh->mkdir (mode))
289 res = 0;
290 delete fh;
291
292 done:
293 syscall_printf ("%d = mkdir (%s, %d)", res, dir, mode);
294 return res;
295 }
296
297 /* rmdir: POSIX 5.5.2.1 */
298 extern "C" int
299 rmdir (const char *dir)
300 {
301 int res = -1;
302 fhandler_base *fh = NULL;
303
304 myfault efault;
305 if (efault.faulted (EFAULT))
306 return -1;
307
308 if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW)))
309 goto done; /* errno already set */;
310
311 if (fh->error ())
312 {
313 debug_printf ("got %d error from build_fh_name", fh->error ());
314 set_errno (fh->error ());
315 }
316 else if (!fh->exists ())
317 set_errno (ENOENT);
318 else if (has_dot_last_component (dir, false))
319 set_errno (EINVAL);
320 else if (!fh->rmdir ())
321 res = 0;
322
323 delete fh;
324
325 done:
326 syscall_printf ("%d = rmdir (%s)", res, dir);
327 return res;
328 }
This page took 0.047558 seconds and 5 git commands to generate.