]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/dir.cc
c7edd887146d1e5a487ff44972ef13aa8d2cd9ff
1 /* dir.cc: Posix directory-related routines
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 #define _COMPILING_NEWLIB
28 /* Return whether the directory of a file is writable. Return 1 if it
29 is. Otherwise, return 0, and set errno appropriately. */
31 writable_directory (const char *file
)
34 char dir
[strlen (file
) + 1];
39 char *slash
= strrchr (dir
, '\\');
42 else if (slash
== dir
)
52 int acc
= access (usedir
, W_OK
);
63 if (check_null_invalid_struct_errno (dir
))
65 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
68 syscall_printf ("-1 = dirfd (%p)", dir
);
71 return dir
->__d_dirent
->d_fd
;
78 opendir_saw_dot_dot
= 2,
82 /* opendir: POSIX 5.1.2.1 */
84 opendir (const char *name
)
90 fh
= cygheap
->fdtab
.build_fhandler_from_name (-1, name
, NULL
, pc
,
91 PC_SYM_FOLLOW
| PC_FULL
, NULL
);
94 else if (pc
.exists ())
95 res
= fh
->opendir (pc
);
109 /* readdir: POSIX 5.1.2.1 */
110 extern "C" struct dirent
*
113 if (check_null_invalid_struct_errno (dir
))
116 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
119 syscall_printf ("%p = readdir (%p)", NULL
, dir
);
123 dirent
*res
= ((fhandler_base
*) dir
->__fh
)->readdir (dir
);
127 if (!(dir
->__flags
& opendir_saw_dot
))
129 res
= dir
->__d_dirent
;
130 strcpy (res
->d_name
, ".");
131 dir
->__flags
|= opendir_saw_dot
;
133 else if (!(dir
->__flags
& opendir_saw_dot_dot
))
135 res
= dir
->__d_dirent
;
136 strcpy (res
->d_name
, "..");
137 dir
->__flags
|= opendir_saw_dot_dot
;
143 /* Compute d_ino by combining filename hash with the directory hash
144 (which was stored in dir->__d_dirhash when opendir was called). */
145 if (res
->d_name
[0] == '.')
147 if (res
->d_name
[1] == '\0')
149 dir
->__d_dirent
->d_ino
= dir
->__d_dirhash
;
150 dir
->__flags
|= opendir_saw_dot
;
152 else if (res
->d_name
[1] != '.' || res
->d_name
[2] != '\0')
156 dir
->__flags
|= opendir_saw_dot_dot
;
157 char *p
, up
[strlen (dir
->__d_dirname
) + 1];
158 strcpy (up
, dir
->__d_dirname
);
159 if (!(p
= strrchr (up
, '\\')))
162 if (!(p
= strrchr (up
, '\\')))
163 dir
->__d_dirent
->d_ino
= hash_path_name (0, ".");
167 dir
->__d_dirent
->d_ino
= hash_path_name (0, up
);
174 __ino64_t dino
= hash_path_name (dir
->__d_dirhash
, "\\");
175 dir
->__d_dirent
->d_ino
= hash_path_name (dino
, res
->d_name
);
177 res
->__ino32
= dir
->__d_dirent
->d_ino
; // for legacy applications
185 if (check_null_invalid_struct_errno (dir
))
188 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
190 return ((fhandler_base
*) dir
->__fh
)->telldir (dir
);
197 return telldir64 (dir
);
201 seekdir64 (DIR *dir
, _off64_t loc
)
203 if (check_null_invalid_struct_errno (dir
))
206 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
209 return ((fhandler_base
*) dir
->__fh
)->seekdir (dir
, loc
);
214 seekdir (DIR *dir
, _off_t loc
)
216 seekdir64 (dir
, (_off64_t
)loc
);
219 /* rewinddir: POSIX 5.1.2.1 */
223 if (check_null_invalid_struct_errno (dir
))
226 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
229 return ((fhandler_base
*) dir
->__fh
)->rewinddir (dir
);
232 /* closedir: POSIX 5.1.2.1 */
236 if (check_null_invalid_struct_errno (dir
))
239 if (dir
->__d_cookie
!= __DIRENT_COOKIE
)
242 syscall_printf ("-1 = closedir (%p)", dir
);
246 /* Reset the marker in case the caller tries to use `dir' again. */
249 int res
= ((fhandler_base
*) dir
->__fh
)->closedir (dir
);
251 cygheap
->fdtab
.release (dir
->__d_dirent
->d_fd
);
253 free (dir
->__d_dirname
);
254 free (dir
->__d_dirent
);
256 syscall_printf ("%d = closedir (%p)", res
);
260 /* mkdir: POSIX 5.4.1.1 */
262 mkdir (const char *dir
, mode_t mode
)
265 SECURITY_ATTRIBUTES sa
= sec_none_nih
;
267 path_conv
real_dir (dir
, PC_SYM_NOFOLLOW
);
271 set_errno (real_dir
.case_clash
? ECASECLASH
: real_dir
.error
);
275 nofinalslash (real_dir
.get_win32 (), real_dir
.get_win32 ());
276 if (! writable_directory (real_dir
.get_win32 ()))
279 if (allow_ntsec
&& real_dir
.has_acls ())
280 set_security_attribute (S_IFDIR
| ((mode
& 07777) & ~cygheap
->umask
),
281 &sa
, alloca (4096), 4096);
283 if (CreateDirectoryA (real_dir
.get_win32 (), &sa
))
285 if (!allow_ntsec
&& allow_ntea
)
286 set_file_attribute (real_dir
.has_acls (), real_dir
.get_win32 (),
287 S_IFDIR
| ((mode
& 07777) & ~cygheap
->umask
));
288 #ifdef HIDDEN_DOT_FILES
289 char *c
= strrchr (real_dir
.get_win32 (), '\\');
290 if ((c
&& c
[1] == '.') || *real_dir
.get_win32 () == '.')
291 SetFileAttributes (real_dir
.get_win32 (), FILE_ATTRIBUTE_HIDDEN
);
299 syscall_printf ("%d = mkdir (%s, %d)", res
, dir
, mode
);
303 /* rmdir: POSIX 5.5.2.1 */
305 rmdir (const char *dir
)
310 path_conv
real_dir (dir
, PC_SYM_NOFOLLOW
);
313 set_errno (real_dir
.error
);
314 else if ((devn
= real_dir
.get_devn ()) == FH_PROC
|| devn
== FH_REGISTRY
315 || devn
== FH_PROCESS
)
317 else if (!real_dir
.exists ())
319 else if (!real_dir
.isdir ())
323 /* Even own directories can't be removed if R/O attribute is set. */
324 if (real_dir
.has_attribute (FILE_ATTRIBUTE_READONLY
))
325 SetFileAttributes (real_dir
,
326 (DWORD
) real_dir
& ~FILE_ATTRIBUTE_READONLY
);
328 if (RemoveDirectory (real_dir
))
330 /* RemoveDirectory on a samba drive doesn't return an error if the
331 directory can't be removed because it's not empty. Checking for
332 existence afterwards keeps us informed about success. */
333 if (GetFileAttributes (real_dir
) != INVALID_FILE_ATTRIBUTES
)
334 set_errno (ENOTEMPTY
);
340 /* This kludge detects if we are attempting to remove the current working
341 directory. If so, we will move elsewhere to potentially allow the
342 rmdir to succeed. This means that cygwin's concept of the current working
343 directory != Windows concept but, hey, whaddaregonnado?
344 Note that this will not cause something like the following to work:
347 since the shell will have foo "open" in the above case and so Windows will
348 not allow the deletion.
349 FIXME: A potential workaround for this is for cygwin apps to *never* call
350 SetCurrentDirectory. */
351 if (strcasematch (real_dir
, cygheap
->cwd
.win32
)
352 && !strcasematch ("c:\\", cygheap
->cwd
.win32
))
354 DWORD err
= GetLastError ();
355 if (!SetCurrentDirectory ("c:\\"))
357 else if ((res
= rmdir (dir
)))
358 SetCurrentDirectory (cygheap
->cwd
.win32
);
362 if (GetLastError () != ERROR_ACCESS_DENIED
363 || !wincap
.access_denied_on_delete ())
366 set_errno (ENOTEMPTY
); /* On 9X ERROR_ACCESS_DENIED is
367 returned if you try to remove a
368 non-empty directory. */
370 /* If directory still exists, restore R/O attribute. */
371 if (real_dir
.has_attribute (FILE_ATTRIBUTE_READONLY
))
372 SetFileAttributes (real_dir
, real_dir
);
377 syscall_printf ("%d = rmdir (%s)", res
, dir
);
This page took 0.049421 seconds and 4 git commands to generate.