From f3810c7281c1e3dca7df0b3e013c73c25bb98954 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 22 Sep 2005 15:52:02 +0000 Subject: [PATCH] * fhandler.h (fhandler_base::fstat_helper): Declare with additional file attributes argument. * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Use file attributes evaluated from NtQueryFileInformation or FileInformationByHandle in call to fstat_helper. Set pc.fileattr from just evaluated file attributes here. (fhandler_base::fstat_by_name): Use file attributes evaluated from FindFileFirst or default attribute in call to fstat_helper. Set pc.fileattr from just evaluated file attributes here. (fhandler_base::fstat_helper): Use file attributes given as argument, not file attributes stored in this fhandler, since this information is potentially wrong. Add comment to explain this. * path.h (has_attribute): New global inline function. (path_conv::set_attributes): New method to change fileattr. --- winsup/cygwin/ChangeLog | 17 +++++++ winsup/cygwin/fhandler.h | 3 +- winsup/cygwin/fhandler_disk_file.cc | 78 ++++++++++++++++++----------- winsup/cygwin/path.h | 8 +++ 4 files changed, 75 insertions(+), 31 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 4ef024980..7c4c8a140 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2005-09-22 Corinna Vinschen + + * fhandler.h (fhandler_base::fstat_helper): Declare with additional + file attributes argument. + * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Use + file attributes evaluated from NtQueryFileInformation or + FileInformationByHandle in call to fstat_helper. + Set pc.fileattr from just evaluated file attributes here. + (fhandler_base::fstat_by_name): Use file attributes evaluated from + FindFileFirst or default attribute in call to fstat_helper. + Set pc.fileattr from just evaluated file attributes here. + (fhandler_base::fstat_helper): Use file attributes given as argument, + not file attributes stored in this fhandler, since this information + is potentially wrong. Add comment to explain this. + * path.h (has_attribute): New global inline function. + (path_conv::set_attributes): New method to change fileattr. + 2005-09-21 Christopher Faylor * cygthread.cc (cygthread::operator new): Just use getenv() to look for diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index f371ee0ce..bdc73bfbf 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -272,7 +272,8 @@ class fhandler_base LONGLONG nAllocSize, DWORD nFileIndexHigh, DWORD nFileIndexLow, - DWORD nNumberOfLinks) + DWORD nNumberOfLinks, + DWORD dwFileAttributes) __attribute__ ((regparm (3))); int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2))); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 45d92dc23..6c4ff04ec 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -124,22 +124,26 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size, FileAllInformation); if (NT_SUCCESS (status)) - /* If the change time is 0, it's a file system which doesn't - support a change timestamp. In that case use the LastWriteTime - entry, as in other calls to fstat_helper. */ - return fstat_helper (buf, - pfai->BasicInformation.ChangeTime.QuadPart ? - *(FILETIME *) &pfai->BasicInformation.ChangeTime : - *(FILETIME *) &pfai->BasicInformation.LastWriteTime, - *(FILETIME *) &pfai->BasicInformation.LastAccessTime, - *(FILETIME *) &pfai->BasicInformation.LastWriteTime, - pfvi->VolumeSerialNumber, - pfai->StandardInformation.EndOfFile.HighPart, - pfai->StandardInformation.EndOfFile.LowPart, - pfai->StandardInformation.AllocationSize.QuadPart, - pfai->InternalInformation.IndexNumber.HighPart, - pfai->InternalInformation.IndexNumber.LowPart, - pfai->StandardInformation.NumberOfLinks); + { + /* If the change time is 0, it's a file system which doesn't + support a change timestamp. In that case use the LastWriteTime + entry, as in other calls to fstat_helper. */ + pc.set_attributes (pfai->BasicInformation.FileAttributes); + return fstat_helper (buf, + pfai->BasicInformation.ChangeTime.QuadPart ? + *(FILETIME *) &pfai->BasicInformation.ChangeTime : + *(FILETIME *) &pfai->BasicInformation.LastWriteTime, + *(FILETIME *) &pfai->BasicInformation.LastAccessTime, + *(FILETIME *) &pfai->BasicInformation.LastWriteTime, + pfvi->VolumeSerialNumber, + pfai->StandardInformation.EndOfFile.HighPart, + pfai->StandardInformation.EndOfFile.LowPart, + pfai->StandardInformation.AllocationSize.QuadPart, + pfai->InternalInformation.IndexNumber.HighPart, + pfai->InternalInformation.IndexNumber.LowPart, + pfai->StandardInformation.NumberOfLinks, + pfai->BasicInformation.FileAttributes); + } debug_printf ("%u = NtQueryInformationFile)", RtlNtStatusToDosError (status)); @@ -160,6 +164,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) local.nFileSizeLow = 0; } + pc.set_attributes (local.dwFileAttributes); return fstat_helper (buf, local.ftLastWriteTime, /* see fstat_helper comment */ local.ftLastAccessTime, @@ -170,7 +175,8 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) -1LL, local.nFileIndexHigh, local.nFileIndexLow, - local.nNumberOfLinks); + local.nNumberOfLinks, + local.dwFileAttributes); } int __stdcall @@ -189,6 +195,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf) else if ((handle = FindFirstFile (pc, &local)) != INVALID_HANDLE_VALUE) { FindClose (handle); + pc.set_attributes (local.dwFileAttributes); res = fstat_helper (buf, local.ftLastWriteTime, /* see fstat_helper comment */ local.ftLastAccessTime, @@ -199,12 +206,14 @@ fhandler_base::fstat_by_name (struct __stat64 *buf) -1LL, 0, 0, - 1); + 1, + local.dwFileAttributes); } else if (pc.isdir ()) { FILETIME ft = {}; - res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, -1LL, 0, 0, 1); + res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, -1LL, 0, 0, 1, + FILE_ATTRIBUTE_DIRECTORY); } else { @@ -270,7 +279,11 @@ fhandler_base::fstat_fs (struct __stat64 *buf) it's faked using the LastWriteTime entry from GetFileInformationByHandle or FindFirstFile. We're deliberatly not using the creation time anymore to simplify interaction with native Windows applications which choke on - creation times >= access or write times. */ + creation times >= access or write times. + + Note that the dwFileAttributes member of the file information evaluated + in the calling function is used here, not the pc.fileattr member, since + the latter might be old and not reflect the actual state of the file. */ int __stdcall fhandler_base::fstat_helper (struct __stat64 *buf, FILETIME ftChangeTime, @@ -282,7 +295,8 @@ fhandler_base::fstat_helper (struct __stat64 *buf, LONGLONG nAllocSize, DWORD nFileIndexHigh, DWORD nFileIndexLow, - DWORD nNumberOfLinks) + DWORD nNumberOfLinks, + DWORD dwFileAttributes) { IO_STATUS_BLOCK st; FILE_COMPRESSION_INFORMATION fci; @@ -328,11 +342,11 @@ fhandler_base::fstat_helper (struct __stat64 *buf, /* A successful NtQueryInformationFile returns the allocation size correctly for compressed and sparse files as well. */ buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE; - else if (pc.has_attribute (FILE_ATTRIBUTE_COMPRESSED - | FILE_ATTRIBUTE_SPARSE_FILE) - && get_io_handle () && !is_fs_special () - && !NtQueryInformationFile (get_io_handle (), &st, (PVOID) &fci, - sizeof fci, FileCompressionInformation)) + else if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_COMPRESSED + | FILE_ATTRIBUTE_SPARSE_FILE) + && get_io_handle () && !is_fs_special () + && !NtQueryInformationFile (get_io_handle (), &st, (PVOID) &fci, + sizeof fci, FileCompressionInformation)) /* Otherwise we request the actual amount of bytes allocated for compressed and sparsed files. */ buf->st_blocks = (fci.CompressedSize.QuadPart + S_BLKSIZE - 1) / S_BLKSIZE; @@ -357,11 +371,14 @@ fhandler_base::fstat_helper (struct __stat64 *buf, else if (pc.issocket ()) buf->st_mode = S_IFSOCK; - if (!get_file_attribute (pc.has_acls (), is_fs_special () ? NULL: get_io_handle (), - get_win32_name (), &buf->st_mode, &buf->st_uid, &buf->st_gid)) + if (!get_file_attribute (pc.has_acls (), + is_fs_special () ? NULL: get_io_handle (), + get_win32_name (), &buf->st_mode, + &buf->st_uid, &buf->st_gid)) { /* If read-only attribute is set, modify ntsec return value */ - if (pc.has_attribute (FILE_ATTRIBUTE_READONLY) && !pc.issymlink ()) + if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY) + && !pc.issymlink ()) buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); if (buf->st_mode & S_IFMT) @@ -378,7 +395,8 @@ fhandler_base::fstat_helper (struct __stat64 *buf, { buf->st_mode |= STD_RBITS; - if (!pc.has_attribute (FILE_ATTRIBUTE_READONLY) && !pc.issymlink ()) + if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY) + && !pc.issymlink ()) buf->st_mode |= STD_WBITS; /* | S_IWGRP | S_IWOTH; we don't give write to group etc */ diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 14c23ebe5..de37ff2ac 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -14,6 +14,13 @@ details. */ #include #include +inline bool +has_attribute (DWORD attributes, DWORD attribs_to_test) +{ + return attributes != INVALID_FILE_ATTRIBUTES + && (attributes & attribs_to_test); +} + enum executable_states { is_executable, @@ -161,6 +168,7 @@ class path_conv bool isro () const {return !!(path_flags & PATH_RO);} bool exists () const {return fileattr != INVALID_FILE_ATTRIBUTES;} bool has_attribute (DWORD x) const {return exists () && (fileattr & x);} + void set_attributes (DWORD x) {fileattr = x;} int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);} executable_states exec_state () {