diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c185a0a08..70ef991b1 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2010-09-30 Corinna Vinschen + + * fhandler.cc: Drop including nfs.h. + * fhandler_disk_file.cc: Ditto. + (fhandler_base::fstat_by_nfs_ea): Use fattr3 from path_conv member, + unless called from fstat. + * path.cc: Drop including nfs.h. + (symlink_info::check): Rearrange definition of file info buffers. + Fetch fattr3 info for files on NFS and store in conv_hdl for later + use in fhandler_base::fstat_by_nfs_ea. Use fattr3 file type to + recognize symlink on NFS and try to fetch symlink target only for + actual symlinks. + * path.h: Include nfs.h. + (class path_conv_handle): Change file info storage to union of + FILE_NETWORK_OPEN_INFORMATION and fattr3 structures. + (path_conv_handle::fnoi): Align to aforementioned change. + (path_conv_handle::nfsattr): New method. + (path_conv::nfsattr): New method. + 2010-09-30 Corinna Vinschen * path.cc (symlink_info::check): Remove erroneous assumption about diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index ce5f79b2e..c97cc0139 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -28,7 +28,6 @@ details. */ #include "ntdll.h" #include "cygtls.h" #include "sigproc.h" -#include "nfs.h" static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 85be07c3d..7f314ed19 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -23,7 +23,6 @@ details. */ #include "pinfo.h" #include "ntdll.h" #include "tls_pbuf.h" -#include "nfs.h" #include "pwdgrp.h" #include @@ -303,51 +302,51 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf) struct { FILE_GET_EA_INFORMATION fgei; char buf[sizeof (NFS_V3_ATTR)]; - } fgei_buf; + } fgei_buf; + fattr3 *nfs_attr = pc.nfsattr (); - /* NFS stumbles over its own caching. If you write to the file, - a subsequent fstat does not return the actual size of the file, - but the size at the time the handle has been opened. Unless - access through another handle invalidates the caching within the - NFS client. */ - if (get_io_handle () && (get_access () & GENERIC_WRITE)) - FlushFileBuffers (get_io_handle ()); - - fgei_buf.fgei.NextEntryOffset = 0; - fgei_buf.fgei.EaNameLength = sizeof (NFS_V3_ATTR) - 1; - stpcpy (fgei_buf.fgei.EaName, NFS_V3_ATTR); - status = NtQueryEaFile (get_stat_handle (), &io, - &ffei_buf.ffei, sizeof ffei_buf, TRUE, - &fgei_buf.fgei, sizeof fgei_buf, NULL, TRUE); - if (NT_SUCCESS (status)) + if (get_io_handle ()) { - fattr3 *nfs_attr = (fattr3 *) (ffei_buf.ffei.EaName - + ffei_buf.ffei.EaNameLength + 1); - buf->st_dev = nfs_attr->fsid; - buf->st_ino = nfs_attr->fileid; - buf->st_mode = (nfs_attr->mode & 0xfff) - | nfs_type_mapping[nfs_attr->type & 7]; - buf->st_nlink = nfs_attr->nlink; - /* FIXME: How to convert UNIX uid/gid to Windows SIDs? */ -#if 0 - buf->st_uid = nfs_attr->uid; - buf->st_gid = nfs_attr->gid; -#else - buf->st_uid = myself->uid; - buf->st_gid = myself->gid; -#endif - buf->st_rdev = makedev (nfs_attr->rdev.specdata1, - nfs_attr->rdev.specdata2); - buf->st_size = nfs_attr->size; - buf->st_blksize = PREFERRED_IO_BLKSIZE; - buf->st_blocks = nfs_attr->used / 512; - buf->st_atim = nfs_attr->atime; - buf->st_mtim = nfs_attr->mtime; - buf->st_ctim = nfs_attr->ctime; - return 0; + /* NFS stumbles over its own caching. If you write to the file, + a subsequent fstat does not return the actual size of the file, + but the size at the time the handle has been opened. Unless + access through another handle invalidates the caching within the + NFS client. */ + if (get_access () & GENERIC_WRITE) + FlushFileBuffers (get_io_handle ()); + + fgei_buf.fgei.NextEntryOffset = 0; + fgei_buf.fgei.EaNameLength = sizeof (NFS_V3_ATTR) - 1; + stpcpy (fgei_buf.fgei.EaName, NFS_V3_ATTR); + status = NtQueryEaFile (get_io_handle (), &io, + &ffei_buf.ffei, sizeof ffei_buf, TRUE, + &fgei_buf.fgei, sizeof fgei_buf, NULL, TRUE); + if (NT_SUCCESS (status)) + nfs_attr = (fattr3 *) (ffei_buf.ffei.EaName + + ffei_buf.ffei.EaNameLength + 1); } - debug_printf ("%p = NtQueryEaFile(%S)", status, pc.get_nt_native_path ()); - return -1; + buf->st_dev = nfs_attr->fsid; + buf->st_ino = nfs_attr->fileid; + buf->st_mode = (nfs_attr->mode & 0xfff) + | nfs_type_mapping[nfs_attr->type & 7]; + buf->st_nlink = nfs_attr->nlink; + /* FIXME: How to convert UNIX uid/gid to Windows SIDs? */ +#if 0 + buf->st_uid = nfs_attr->uid; + buf->st_gid = nfs_attr->gid; +#else + buf->st_uid = myself->uid; + buf->st_gid = myself->gid; +#endif + buf->st_rdev = makedev (nfs_attr->rdev.specdata1, + nfs_attr->rdev.specdata2); + buf->st_size = nfs_attr->size; + buf->st_blksize = PREFERRED_IO_BLKSIZE; + buf->st_blocks = nfs_attr->used / 512; + buf->st_atim = nfs_attr->atime; + buf->st_mtim = nfs_attr->mtime; + buf->st_ctim = nfs_attr->ctime; + return 0; } int __stdcall diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index c1f306efa..8c98e4dab 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -67,7 +67,6 @@ #include "cygtls.h" #include "tls_pbuf.h" #include "environ.h" -#include "nfs.h" #include #include #include @@ -2398,9 +2397,6 @@ 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%). */ @@ -2408,17 +2404,34 @@ restart: { 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); + struct { + FILE_FULL_EA_INFORMATION ffei; + char buf[sizeof (NFS_V3_ATTR) + sizeof (fattr3)]; + } ffei_buf; + struct { + FILE_GET_EA_INFORMATION fgei; + char buf[sizeof (NFS_V3_ATTR)]; + } fgei_buf; + + fgei_buf.fgei.NextEntryOffset = 0; + fgei_buf.fgei.EaNameLength = sizeof (NFS_V3_ATTR) - 1; + stpcpy (fgei_buf.fgei.EaName, NFS_V3_ATTR); + status = NtQueryEaFile (h, &io, &ffei_buf.ffei, sizeof ffei_buf, + TRUE, &fgei_buf.fgei, sizeof fgei_buf, + NULL, TRUE); if (NT_SUCCESS (status)) - fileattr = fbi.FileAttributes; + { + fattr3 *nfs_attr = (fattr3 *) + (ffei_buf.ffei.EaName + ffei_buf.ffei.EaNameLength + 1); + memcpy (conv_hdl.nfsattr (), nfs_attr, sizeof (fattr3)); + fileattr = ((nfs_attr->type & 7) == NF3DIR) + ? FILE_ATTRIBUTE_DIRECTORY : 0; + } } else { + PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi (); + status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi, FileNetworkOpenInformation); if ((status == STATUS_INVALID_PARAMETER @@ -2428,6 +2441,8 @@ restart: /* This occurs when accessing SMB share root dirs hosted on NT4 (STATUS_INVALID_PARAMETER), or when trying to access SMB share root dirs from NT4 (STATUS_NOT_IMPLEMENTED). */ + FILE_BASIC_INFORMATION fbi; + status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, FileBasicInformation); if (NT_SUCCESS (status)) @@ -2529,6 +2544,8 @@ restart: } else { + PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi (); + fileattr = fdi_buf.fdi.FileAttributes; memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi); /* Amazing, but true: The FILE_NETWORK_OPEN_INFORMATION @@ -2627,7 +2644,7 @@ restart: else if (res) { /* A symlink is never a directory. */ - pfnoi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; + conv_hdl.fnoi ()->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; break; } } @@ -2649,7 +2666,7 @@ restart: /* If the file is on an NFS share and could be opened with extended attributes, check if it's a symlink. Only files can be symlinks (which can be symlinks to directories). */ - else if (fs.is_nfs () && !no_ea && !(fileattr & FILE_ATTRIBUTE_DIRECTORY)) + else if (fs.is_nfs () && (conv_hdl.nfsattr ()->type & 7) == NF3LNK) { res = check_nfs_symlink (h); if (res) diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index fae721664..764381a4a 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -12,6 +12,7 @@ details. */ #include "devices.h" #include "mount.h" #include "cygheap_malloc.h" +#include "nfs.h" #include #include @@ -96,17 +97,21 @@ 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; + union { + /* 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; + /* For NFS. */ + fattr3 _fattr3; + } attribs; public: path_conv_handle () : hdl (NULL), acc (0) {} inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; } @@ -129,7 +134,9 @@ 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; } + { return (struct _FILE_NETWORK_OPEN_INFORMATION *) &attribs._fnoi; } + inline struct fattr3 *nfsattr () + { return (struct fattr3 *) &attribs._fattr3; } }; class path_conv @@ -321,6 +328,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 (); } + struct fattr3 *nfsattr () { return conv_handle.nfsattr (); } void reset_conv_handle () { conv_handle.set (NULL, 0); } void close_conv_handle () { conv_handle.close (); }