aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-08-14 13:39:07 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-08-14 13:39:07 +0000
commite5756789456af7c2b09f1adfe7635e15e701bd29 (patch)
tree5f0b14028fea859eacbe3c30a7ab63eb0794cdef
parentc1999c4b0c262112ca1fa38fcd1558b9e91a7bf0 (diff)
downloadnewlib-e5756789456af7c2b09f1adfe7635e15e701bd29.zip
newlib-e5756789456af7c2b09f1adfe7635e15e701bd29.tar.gz
newlib-e5756789456af7c2b09f1adfe7635e15e701bd29.tar.bz2
* fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Remove
ill-advised attempt to optimize "." and ".." handling by checking for specific position in directory listing. Explain why. (fhandler_disk_file.cc (fhandler_disk_file::readdir): Ditto. Special-case opening file on NFS to fetch inode number and add longish comment to explain why.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc63
2 files changed, 55 insertions, 17 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3e7336c..8aaa8fb 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
2009-08-14 Corinna Vinschen <corinna@vinschen.de>
+ * fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Remove
+ ill-advised attempt to optimize "." and ".." handling by checking for
+ specific position in directory listing. Explain why.
+ (fhandler_disk_file.cc (fhandler_disk_file::readdir): Ditto.
+ Special-case opening file on NFS to fetch inode number and add longish
+ comment to explain why.
+
+2009-08-14 Corinna Vinschen <corinna@vinschen.de>
+
* (fhandler_socket::getsockname): Fix length returned for unbound
AF_LOCAL sockets.
(fhandler_socket::getpeername): Ditto.
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 579c6ef..0c0f2bc 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1828,10 +1828,16 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR));
- if (dir->__d_position == 0 && !strcmp (de->d_name, "."))
- dir->__flags |= dirent_saw_dot;
- else if (dir->__d_position == 1 && !strcmp (de->d_name, ".."))
- dir->__flags |= dirent_saw_dot_dot;
+ /* Don't try to optimize relative to dir->__d_position. On several
+ filesystems it's no safe bet that "." and ".." entries always
+ come first. */
+ if (de->d_name[0] == '.')
+ {
+ if (de->d_name[1] == '\0')
+ dir->__flags |= dirent_saw_dot;
+ else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
+ dir->__flags |= dirent_saw_dot_dot;
+ }
return 0;
}
@@ -1960,28 +1966,51 @@ go_ahead:
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{
- OBJECT_ATTRIBUTES attr;
-
- if (dir->__d_position == 0 && FileNameLength == 2
- && FileName[0] == '.')
+ /* Don't try to optimize relative to dir->__d_position. On several
+ filesystems it's no safe bet that "." and ".." entries always
+ come first. */
+ if (FileNameLength == sizeof (WCHAR) && FileName[0] == '.')
de->d_ino = get_ino_by_handle (pc, get_handle ());
- else if (dir->__d_position == 1 && FileNameLength == 4
+ else if (FileNameLength == sizeof (WCHAR)
&& FileName[0] == L'.' && FileName[1] == L'.')
- if (!(dir->__flags & dirent_isroot))
- de->d_ino = readdir_get_ino (get_name (), true);
- else
- de->d_ino = get_ino_by_handle (pc, get_handle ());
+ {
+ if (!(dir->__flags & dirent_isroot))
+ de->d_ino = readdir_get_ino (get_name (), true);
+ else
+ de->d_ino = get_ino_by_handle (pc, get_handle ());
+ }
else
{
+ OBJECT_ATTRIBUTES attr;
HANDLE hdl;
+ NTSTATUS f_status;
InitializeObjectAttributes (&attr, &fname,
pc.objcaseinsensitive (),
get_handle (), NULL);
- if (NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
- FILE_SHARE_VALID_FLAGS,
- FILE_OPEN_FOR_BACKUP_INTENT
- | FILE_OPEN_REPARSE_POINT)))
+ /* FILE_OPEN_REPARSE_POINT on NFS is a no-op, so the normal
+ NtOpenFile here returns the inode number of the symlink target,
+ rather than the inode number of the symlink itself.
+
+ Worse, trying to open a symlink without setting the special
+ "ActOnSymlink" EA triggers a bug in Windows 7 which results
+ in a timeout of about 20 seconds, followed by two exceptions
+ in the NT kernel.
+
+ Since both results are far from desirable, we open symlinks
+ on NFS so that we get the right inode and a happy W7.
+ And, since some filesystems choke on the EAs, we don't
+ use them unconditionally. */
+ f_status = (dir->__flags & dirent_nfs_d_ino)
+ ? NtCreateFile (&hdl, READ_CONTROL, &attr, &io,
+ NULL, 0, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN, FILE_OPEN_FOR_BACKUP_INTENT,
+ &nfs_aol_ffei, sizeof nfs_aol_ffei)
+ : NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_OPEN_REPARSE_POINT);
+ if (NT_SUCCESS (f_status))
{
de->d_ino = get_ino_by_handle (pc, hdl);
NtClose (hdl);