From c80480bfa06d18700c434d034db4915fc358efab Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 13 Sep 2010 11:17:36 +0000 Subject: [PATCH] * fhandler.h (class fhandler_base): Change inheritance of fstat_helper and fstat_by_... methods to private. (fhandler_base::fstat_helper): Drop all redundant arguments. * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call to fstat_by_nfs_ea here. Drop fetching basic file information. Drop setting file attributes. Accommodate change in fstat_helper call. (fhandler_base::fstat_by_name): Simplify. Only fetch directory information to get the inode number. Drop setting file attributes. Accommodate change in fstat_helper call. (fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS. (fhandler_base::fstat_helper): Drop all redundant arguments. Use information already collected in the fhandler. Move heading comment into code and drop dwFileAttributes comment. * mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle. * mount.cc (fs_info::update): Note that has_buggy_basic_info is unused. * path.cc (symlink_info::check_reparse_point): Add comment. (symlink_info::check): Fetch FileNetworkOpenInformation rather than FileBasicInformation throughout, except on NFS. Explain why. Store FILE_NETWORK_OPEN_INFORMATION in conv_hdl. Remove FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point symlinks. * path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION member _fnoi. (path_conv_handle::fnoi): New accessor method for _fnoi. (path_conv::fnoi): New accessor method for cubv_hdl._fnoi. * fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method. --- winsup/cygwin/ChangeLog | 30 ++++ winsup/cygwin/fhandler.h | 15 +- winsup/cygwin/fhandler_disk_file.cc | 204 ++++++++-------------------- winsup/cygwin/fhandler_tty.cc | 2 +- winsup/cygwin/mmap.cc | 4 +- winsup/cygwin/mount.cc | 3 +- winsup/cygwin/path.cc | 45 ++++-- winsup/cygwin/path.h | 19 ++- 8 files changed, 144 insertions(+), 178 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 00cfd3209..dbea36cdc 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,33 @@ +2010-09-13 Corinna Vinschen + + * fhandler.h (class fhandler_base): Change inheritance of fstat_helper + and fstat_by_... methods to private. + (fhandler_base::fstat_helper): Drop all redundant arguments. + * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call + to fstat_by_nfs_ea here. Drop fetching basic file information. + Drop setting file attributes. Accommodate change in fstat_helper call. + (fhandler_base::fstat_by_name): Simplify. Only fetch directory + information to get the inode number. Drop setting file attributes. + Accommodate change in fstat_helper call. + (fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS. + (fhandler_base::fstat_helper): Drop all redundant arguments. Use + information already collected in the fhandler. Move heading comment + into code and drop dwFileAttributes comment. + * mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle. + * mount.cc (fs_info::update): Note that has_buggy_basic_info is unused. + * path.cc (symlink_info::check_reparse_point): Add comment. + (symlink_info::check): Fetch FileNetworkOpenInformation rather than + FileBasicInformation throughout, except on NFS. Explain why. Store + FILE_NETWORK_OPEN_INFORMATION in conv_hdl. Remove + FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point + symlinks. + * path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION + member _fnoi. + (path_conv_handle::fnoi): New accessor method for _fnoi. + (path_conv::fnoi): New accessor method for cubv_hdl._fnoi. + + * fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method. + 2010-09-12 Corinna Vinschen * sec_acl.cc (acl_worker): Remove. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 3fcfe1cef..8e232f0c4 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -293,21 +293,14 @@ class fhandler_base int close_fs () { return fhandler_base::close (); } virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2))); +private: int __stdcall fstat_helper (struct __stat64 *buf, - PLARGE_INTEGER ChangeTime, - PLARGE_INTEGER LastAccessTime, - PLARGE_INTEGER LastWriteTime, - PLARGE_INTEGER CreationTime, - DWORD dwVolumeSerialNumber, - ULONGLONG nFileSize, - LONGLONG nAllocSize, - ULONGLONG nFileIndex, - DWORD nNumberOfLinks, - DWORD dwFileAttributes) - __attribute__ ((regparm (3))); + DWORD nNumberOfLinks) + __attribute__ ((regparm (3))); int __stdcall fstat_by_nfs_ea (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2))); +public: virtual int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); int utimens_fs (const struct timespec *) __attribute__ ((regparm (2))); virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index c7ecf48e8..b9c62b27a 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -345,43 +345,17 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf) int __stdcall fhandler_base::fstat_by_handle (struct __stat64 *buf) { - NTSTATUS status; - IO_STATUS_BLOCK io; - - if (pc.fs_is_nfs ()) - return fstat_by_nfs_ea (buf); - /* Don't use FileAllInformation info class. It returns a pathname rather than a filename, so it needs a really big buffer for no good reason since we don't need the name anyway. So we just call the three info classes necessary to get all information required by stat(2). */ - - union { - FILE_BASIC_INFORMATION fbi; - FILE_NETWORK_OPEN_INFORMATION fnoi; - } fi; FILE_STANDARD_INFORMATION fsi; FILE_INTERNAL_INFORMATION fii; HANDLE h = get_stat_handle (); + NTSTATUS status = 0; + IO_STATUS_BLOCK io; - if (pc.has_buggy_basic_info ()) - { - status = NtQueryInformationFile (h, &io, &fi, sizeof fi, - FileNetworkOpenInformation); - /* The timestamps are in the same relative memory location, only - the DOS attributes have to be moved. */ - fi.fbi.FileAttributes = fi.fnoi.FileAttributes; - } - else - status = NtQueryInformationFile (h, &io, &fi.fbi, - sizeof fi.fbi, FileBasicInformation); - if (!NT_SUCCESS (status)) - { - debug_printf ("%p = NtQueryInformationFile(%S, FileBasicInformation)", - status, pc.get_nt_native_path ()); - return -1; - } status = NtQueryInformationFile (h, &io, &fsi, sizeof fsi, FileStandardInformation); if (!NT_SUCCESS (status)) @@ -402,26 +376,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) } ino = fii.FileId.QuadPart; } - /* 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. */ - if (pc.is_rep_symlink ()) - fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; - /* Only copy attributes if not a device root dir. */ - if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE)) - pc.file_attributes (fi.fbi.FileAttributes); - return fstat_helper (buf, - fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime - : &fi.fbi.LastWriteTime, - &fi.fbi.LastAccessTime, - &fi.fbi.LastWriteTime, - &fi.fbi.CreationTime, - get_dev (), - fsi.EndOfFile.QuadPart, - fsi.AllocationSize.QuadPart, - ino, - fsi.NumberOfLinks, - fi.fbi.FileAttributes); + return fstat_helper (buf, fsi.NumberOfLinks); } int __stdcall @@ -437,76 +392,35 @@ fhandler_base::fstat_by_name (struct __stat64 *buf) FILE_ID_BOTH_DIR_INFORMATION fdi; WCHAR buf[NAME_MAX + 1]; } fdi_buf; - LARGE_INTEGER FileId; - RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename); - InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (), - NULL, NULL); - if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, - &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_SYNCHRONOUS_IO_NONALERT - | FILE_OPEN_FOR_BACKUP_INTENT - | FILE_DIRECTORY_FILE))) + if (!ino && wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ()) { - debug_printf ("%p = NtOpenFile(%S)", status, pc.get_nt_native_path ()); - goto too_bad; + RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename); + InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (), + NULL, NULL); + status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, + &attr, &io, FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_DIRECTORY_FILE); + if (!NT_SUCCESS (status)) + debug_printf ("%p = NtOpenFile(%S)", status, + pc.get_nt_native_path ()); + else + { + status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io, + &fdi_buf.fdi, sizeof fdi_buf, + FileIdBothDirectoryInformation, + TRUE, &basename, TRUE); + NtClose (dir); + if (!NT_SUCCESS (status)) + debug_printf ("%p = NtQueryDirectoryFile(%S)", status, + pc.get_nt_native_path ()); + else + ino = fdi_buf.fdi.FileId.QuadPart; + } } - if (wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo () - && NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io, - &fdi_buf.fdi, sizeof fdi_buf, - FileIdBothDirectoryInformation, - TRUE, &basename, TRUE))) - FileId = fdi_buf.fdi.FileId; - else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, - &io, &fdi_buf.fdi, - sizeof fdi_buf, - FileBothDirectoryInformation, - TRUE, &basename, TRUE))) - FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */ - if (!NT_SUCCESS (status)) - { - debug_printf ("%p = NtQueryDirectoryFile(%S)", status, - pc.get_nt_native_path ()); - NtClose (dir); - goto too_bad; - } - NtClose (dir); - /* 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. */ - if (pc.is_rep_symlink ()) - fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; - /* Only copy attributes if not a device root dir. */ - if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE)) - pc.file_attributes (fdi_buf.fdi.FileAttributes); - return fstat_helper (buf, - fdi_buf.fdi.ChangeTime.QuadPart - ? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime, - &fdi_buf.fdi.LastAccessTime, - &fdi_buf.fdi.LastWriteTime, - &fdi_buf.fdi.CreationTime, - pc.fs_serial_number (), - fdi_buf.fdi.EndOfFile.QuadPart, - fdi_buf.fdi.AllocationSize.QuadPart, - FileId.QuadPart, - 1, - fdi_buf.fdi.FileAttributes); - -too_bad: - LARGE_INTEGER ft; - /* Arbitrary value: 2006-12-01 */ - RtlSecondsSince1970ToTime (1164931200L, &ft); - return fstat_helper (buf, - &ft, - &ft, - &ft, - &ft, - 0, - 0ULL, - -1LL, - 0ULL, - 1, - pc.file_attributes ()); + return fstat_helper (buf, 1); } int __stdcall @@ -519,7 +433,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf) if (get_stat_handle ()) { if (!nohandle () && !is_fs_special ()) - res = fstat_by_handle (buf); + res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf); if (res) res = fstat_by_name (buf); return res; @@ -540,7 +454,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf) Since fhandler_base::open only calls CloseHandle if !nohandle, we have to set it to false before calling close and restore the state afterwards. */ - res = fstat_by_handle (buf); + res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf); bool no_handle = nohandle (); nohandle (false); close_fs (); @@ -553,39 +467,26 @@ fhandler_base::fstat_fs (struct __stat64 *buf) return res; } -/* The ChangeTime is taken from the NTFS ChangeTime entry, if reading - the file information using NtQueryInformationFile succeeded. If not, - 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. - - 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, - PLARGE_INTEGER ChangeTime, - PLARGE_INTEGER LastAccessTime, - PLARGE_INTEGER LastWriteTime, - PLARGE_INTEGER CreationTime, - DWORD dwVolumeSerialNumber, - ULONGLONG nFileSize, - LONGLONG nAllocSize, - ULONGLONG nFileIndex, - DWORD nNumberOfLinks, - DWORD dwFileAttributes) + DWORD nNumberOfLinks) { IO_STATUS_BLOCK st; FILE_COMPRESSION_INFORMATION fci; HANDLE h = get_stat_handle (); + PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi (); + ULONG attributes = pc.file_attributes (); - to_timestruc_t ((PFILETIME) LastAccessTime, &buf->st_atim); - to_timestruc_t ((PFILETIME) LastWriteTime, &buf->st_mtim); - to_timestruc_t ((PFILETIME) ChangeTime, &buf->st_ctim); - to_timestruc_t ((PFILETIME) CreationTime, &buf->st_birthtim); - buf->st_rdev = buf->st_dev = dwVolumeSerialNumber; - buf->st_size = (_off64_t) nFileSize; + to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim); + to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim); + /* If the ChangeTime is 0, the underlying FS doesn't support this timestamp + (FAT for instance). If so, it's faked using LastWriteTime. */ + to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime + : (PFILETIME) &pfnoi->LastWriteTime, + &buf->st_ctim); + to_timestruc_t ((PFILETIME) &pfnoi->CreationTime, &buf->st_birthtim); + buf->st_rdev = buf->st_dev = get_dev (); + buf->st_size = (_off64_t) pfnoi->EndOfFile.QuadPart; /* The number of links to a directory includes the number of subdirectories in the directory, since all those subdirectories point to it. However, this is painfully slow, so we do without it. */ @@ -596,19 +497,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf, #endif /* Enforce namehash as inode number on untrusted file systems. */ - if (nFileIndex && pc.isgood_inode (nFileIndex)) - buf->st_ino = (__ino64_t) nFileIndex; + if (ino && pc.isgood_inode (ino)) + buf->st_ino = (__ino64_t) ino; else buf->st_ino = get_ino (); buf->st_blksize = PREFERRED_IO_BLKSIZE; - if (nAllocSize >= 0LL) + if (pfnoi->AllocationSize.QuadPart >= 0LL) /* 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 (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_COMPRESSED - | FILE_ATTRIBUTE_SPARSE_FILE) + buf->st_blocks = (pfnoi->AllocationSize.QuadPart + S_BLKSIZE - 1) + / S_BLKSIZE; + else if (::has_attribute (attributes, FILE_ATTRIBUTE_COMPRESSED + | FILE_ATTRIBUTE_SPARSE_FILE) && h && !is_fs_special () && !NtQueryInformationFile (h, &st, (PVOID) &fci, sizeof fci, FileCompressionInformation)) @@ -641,7 +543,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf, &buf->st_mode, &buf->st_uid, &buf->st_gid)) { /* If read-only attribute is set, modify ntsec return value */ - if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY) + if (::has_attribute (attributes, FILE_ATTRIBUTE_READONLY) && !pc.isdir () && !pc.issymlink ()) buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); @@ -660,7 +562,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf, { buf->st_mode |= STD_RBITS; - if (!::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY)) + if (!::has_attribute (attributes, FILE_ATTRIBUTE_READONLY)) buf->st_mode |= STD_WBITS; /* | S_IWGRP | S_IWOTH; we don't give write to group etc */ diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 45ab24bcb..f0f850f42 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -717,7 +717,7 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t) tty process group leader. TODO: Investigate how SIGTTIN should be handled with pure-windows programs. */ - tc->pgid = myself->pgid; + tc->setpgid (myself->pgid); } if (f != INVALID_HANDLE_VALUE) diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 710df06e8..57e0a40e7 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -1,7 +1,7 @@ /* mmap.cc Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -865,7 +865,7 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off) goto out; } - if (fh->fstat_by_handle (&st)) + if (fh->fstat_fs (&st)) { __seterrno (); goto out; diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 8ea1b6295..6c58849b8 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -381,7 +381,8 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) Therefore, for NWFS we have to fallback to the FileNetworkOpenInformation info class. Unfortunately we can't use FileNetworkOpenInformation all the time since that fails on - other filesystems like NFS. */ + other filesystems like NFS. + UNUSED, but keep in for information purposes. */ has_buggy_basic_info (is_nwfs ()); /* Netapp ans NWFS are too dumb to allow non-DOS filesystems containing trailing dots and spaces when accessed from Windows diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 4b8179c8e..470546586 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1946,6 +1946,7 @@ symlink_info::check_reparse_point (HANDLE h) sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer, subst.Length / sizeof (WCHAR)); pflags |= PATH_SYMLINK | PATH_REP; + /* A symlink is never a directory. */ fileattr &= ~FILE_ATTRIBUTE_DIRECTORY; return posixify (srcbuf); } @@ -2238,7 +2239,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs, UNICODE_STRING upath; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; - FILE_BASIC_INFORMATION fbi; suffix_scan suffix; const ULONG ci_flag = cygwin_shared->obcaseinsensitive @@ -2409,16 +2409,34 @@ restart: } } + FILE_BASIC_INFORMATION fbi; + PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi (); + if (NT_SUCCESS (status) /* Check file system while we're having the file open anyway. This speeds up path_conv noticably (~10%). */ - && (fs.inited () || fs.update (&upath, h)) - && NT_SUCCESS (status = fs.has_buggy_basic_info () - ? NtQueryAttributesFile (&attr, &fbi) - : NtQueryInformationFile (h, &io, &fbi, sizeof fbi, - FileBasicInformation))) - fileattr = fbi.FileAttributes; - else + && (fs.inited () || fs.update (&upath, h))) + { + if (fs.is_nfs ()) + { + /* NFS doesn't handle FileNetworkOpenInformation when called + via NtQueryInformationFile (STATUS_INVALID_PARAMETER). + Since we only need FileAttributes for NFS anyway, we just + fetch the FileBasicInformation. */ + status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, + FileBasicInformation); + if (NT_SUCCESS (status)) + fileattr = fbi.FileAttributes; + } + else + { + status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi, + FileNetworkOpenInformation); + if (NT_SUCCESS (status)) + fileattr = pfnoi->FileAttributes; + } + } + if (!NT_SUCCESS (status)) { debug_printf ("%p = NtQueryInformationFile (%S)", status, &upath); fileattr = INVALID_FILE_ATTRIBUTES; @@ -2504,7 +2522,10 @@ restart: fileattr = 0; } else - fileattr = fdi_buf.fdi.FileAttributes; + { + fileattr = fdi_buf.fdi.FileAttributes; + memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi); + } } ext_tacked_on = !!*ext_here; goto file_not_symlink; @@ -2590,7 +2611,11 @@ restart: pflags &= ~PC_KEEP_HANDLE; } else if (res) - break; + { + /* A symlink is never a directory. */ + pfnoi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; + break; + } } /* This is the old Cygwin method creating symlinks. A symlink will diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 3650f7688..f832016e5 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -89,10 +89,24 @@ enum path_types PATH_SOCKET = 0x40000000 }; +class symlink_info; +struct _FILE_NETWORK_OPEN_INFORMATION; + class path_conv_handle { HANDLE hdl; ACCESS_MASK acc; + /* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in + ntdll.h here, though. */ + struct { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + } _fnoi; public: path_conv_handle () : hdl (NULL), acc (0) {} inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; } @@ -114,10 +128,10 @@ public: } inline HANDLE handle () const { return hdl; } inline ACCESS_MASK access () const { return acc; } + inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () + { return (struct _FILE_NETWORK_OPEN_INFORMATION *) &_fnoi; } }; -class symlink_info; - class path_conv { DWORD fileattr; @@ -287,6 +301,7 @@ class path_conv HANDLE handle () const { return conv_handle.handle (); } ACCESS_MASK access () const { return conv_handle.access (); } + struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return conv_handle.fnoi (); } void reset_conv_handle () { conv_handle.set (NULL, 0); } void close_conv_handle () { conv_handle.close (); }