diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8924885df..9eb93adac 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2009-01-29 Corinna Vinschen + + * fhandler_disk_file.cc (fhandler_disk_file::readdir): Fix inode number + evaluation for faked "." entry. + + * mount.cc (fs_info::update): Move setting of is_cdrom after checking + for caseinsensitivity. Recognize UDF in is_cdrom case and set + caseinsensitive flag according to UDF brokenness determined by OS. + Add comment to explain why. + * mount.h (class fs_info): Add is_udf status flag. + * path.cc (symlink_info::check): Add workaround for UDF bug in + terms of casesensitivity on certain OSes. + * wincap.h (wincaps::has_broken_udf): New element. + (wincaps::has_broken_udf): New element + 2009-01-27 Christopher Faylor * fhandler.cc (fhandler_base::wait_overlapped): Set bytes to -1 on diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 2aad2ff79..7fd66b843 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -1928,7 +1928,8 @@ go_ahead: else if (!(dir->__flags & dirent_saw_dot)) { strcpy (de->d_name , "."); - de->d_ino = get_ino_by_handle (get_handle ()); + if (pc.isgood_inode (de->d_ino)) + de->d_ino = get_ino_by_handle (get_handle ()); dir->__d_position++; dir->__flags |= dirent_saw_dot; res = 0; diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 0797d1bb3..a7cc07efb 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -262,7 +262,6 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) } is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE) && !is_samba () && !is_netapp ()); - is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM); has_acls (flags () & FS_PERSISTENT_ACLS); hasgood_inode (((flags () & FILE_PERSISTENT_ACLS) && !is_netapp ()) @@ -274,6 +273,21 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) caseinsensitive ((!(flags () & FILE_CASE_SENSITIVE_SEARCH) || is_samba ()) && !is_nfs ()); + is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM); + if (is_cdrom ()) + { + RtlInitUnicodeString (&testname, L"UDF"); + is_udf (RtlEqualUnicodeString (&fsname, &testname, FALSE)); + /* UDF on NT 5.x is broken (at least) in terms of case sensitivity. The + UDF driver reports the FILE_CASE_SENSITIVE_SEARCH capability but: + - Opening the root directory for query seems to work at first, but the + filenames in the directory listing are mutilated. + - When trying to open a file or directory case sensitive, the file + appears to be non-existant. */ + if (is_udf () && wincap.has_broken_udf ()) + caseinsensitive (true); + } + if (!in_vol) NtClose (vol); return true; diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h index c6c0bb1e0..4537f465a 100644 --- a/winsup/cygwin/mount.h +++ b/winsup/cygwin/mount.h @@ -31,6 +31,7 @@ class fs_info unsigned is_nfs : 1; unsigned is_netapp : 1; unsigned is_cdrom : 1; + unsigned is_udf : 1; } status; ULONG sernum; public: @@ -52,6 +53,7 @@ class fs_info IMPLEMENT_STATUS_FLAG (bool, is_nfs) IMPLEMENT_STATUS_FLAG (bool, is_netapp) IMPLEMENT_STATUS_FLAG (bool, is_cdrom) + IMPLEMENT_STATUS_FLAG (bool, is_udf) ULONG serial_number () const { return sernum; } bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3))); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index aa635103d..ae01109a1 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2140,6 +2140,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, NTSTATUS status; IO_STATUS_BLOCK io; bool no_ea = false; + bool fs_update_called = false; error = 0; get_nt_native_path (suffix.path, upath); @@ -2179,6 +2180,30 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT); } + if (status == STATUS_OBJECT_NAME_NOT_FOUND && ci_flag == 0 + && wincap.has_broken_udf ()) + { + /* On NT 5.x UDF is broken (at least) in terms of case sensitivity. + When trying to open a file case sensitive, the file appears to be + non-existant. Another bug is described in fs_info::update. */ + attr.Attributes = OBJ_CASE_INSENSITIVE; + status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, + &attr, &io, FILE_SHARE_VALID_FLAGS, + FILE_OPEN_REPARSE_POINT + | FILE_OPEN_FOR_BACKUP_INTENT); + attr.Attributes = ci_flag; + if (NT_SUCCESS (status)) + { + fs.update (&upath, h); + if (fs.is_udf ()) + fs_update_called = true; + else + { + NtClose (h); + status = STATUS_OBJECT_NAME_NOT_FOUND; + } + } + } if (NT_SUCCESS (status) && NT_SUCCESS (status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, @@ -2271,7 +2296,8 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, /* Check file system while we're having the file open anyway. This speeds up path_conv noticably (~10%). */ - fs.update (&upath, h); + if (!fs_update_called) + fs.update (&upath, h); ext_tacked_on = !!*ext_here; diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 9fc2b211f..082343a40 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -53,6 +53,7 @@ wincaps wincap_unknown __attribute__((section (".cygwin_dll_common"), shared)) = ts_has_dep_problem:false, has_recvmsg:false, has_sendmsg:false, + has_broken_udf:false, }; wincaps wincap_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -88,6 +89,7 @@ wincaps wincap_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:false, has_sendmsg:false, + has_broken_udf:false, }; wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -123,6 +125,7 @@ wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) = ts_has_dep_problem:false, has_recvmsg:false, has_sendmsg:false, + has_broken_udf:false, }; wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -158,6 +161,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:false, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -193,6 +197,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = ts_has_dep_problem:false, has_recvmsg:false, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -228,6 +233,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:true, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -263,6 +269,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:true, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -298,6 +305,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:true, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -333,6 +341,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:true, has_sendmsg:false, + has_broken_udf:true, }; wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -368,6 +377,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { ts_has_dep_problem:false, has_recvmsg:true, has_sendmsg:true, + has_broken_udf:false, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 703527526..e3ab4d70d 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -45,6 +45,7 @@ struct wincaps unsigned ts_has_dep_problem : 1; unsigned has_recvmsg : 1; unsigned has_sendmsg : 1; + unsigned has_broken_udf : 1; }; class wincapc @@ -96,6 +97,7 @@ public: bool IMPLEMENT (ts_has_dep_problem) bool IMPLEMENT (has_recvmsg) bool IMPLEMENT (has_sendmsg) + bool IMPLEMENT (has_broken_udf) #undef IMPLEMENT };