From: corinna Date: Fri, 14 Aug 2009 13:39:07 +0000 (+0000) Subject: * fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Remove X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c1293344bb7d7beb06f3000affb431edf0eb84ba;p=pf3gnuchains%2Fpf3gnuchains3x.git * 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. --- diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3e7336c1b6..8aaa8fb436 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,14 @@ 2009-08-14 Corinna Vinschen + * 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 + * (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 579c6ef21f..0c0f2bc918 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);