* 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.
This commit is contained in:
Corinna Vinschen 2010-09-30 13:52:34 +00:00
parent ab3cd88858
commit 2d355410b7
5 changed files with 111 additions and 69 deletions

View File

@ -1,3 +1,22 @@
2010-09-30 Corinna Vinschen <corinna@vinschen.de>
* 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 <corinna@vinschen.de> 2010-09-30 Corinna Vinschen <corinna@vinschen.de>
* path.cc (symlink_info::check): Remove erroneous assumption about * path.cc (symlink_info::check): Remove erroneous assumption about

View File

@ -28,7 +28,6 @@ details. */
#include "ntdll.h" #include "ntdll.h"
#include "cygtls.h" #include "cygtls.h"
#include "sigproc.h" #include "sigproc.h"
#include "nfs.h"
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */

View File

@ -23,7 +23,6 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "ntdll.h" #include "ntdll.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include "nfs.h"
#include "pwdgrp.h" #include "pwdgrp.h"
#include <winioctl.h> #include <winioctl.h>
@ -303,51 +302,51 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf)
struct { struct {
FILE_GET_EA_INFORMATION fgei; FILE_GET_EA_INFORMATION fgei;
char buf[sizeof (NFS_V3_ATTR)]; 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, if (get_io_handle ())
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))
{ {
fattr3 *nfs_attr = (fattr3 *) (ffei_buf.ffei.EaName /* NFS stumbles over its own caching. If you write to the file,
+ ffei_buf.ffei.EaNameLength + 1); a subsequent fstat does not return the actual size of the file,
buf->st_dev = nfs_attr->fsid; but the size at the time the handle has been opened. Unless
buf->st_ino = nfs_attr->fileid; access through another handle invalidates the caching within the
buf->st_mode = (nfs_attr->mode & 0xfff) NFS client. */
| nfs_type_mapping[nfs_attr->type & 7]; if (get_access () & GENERIC_WRITE)
buf->st_nlink = nfs_attr->nlink; FlushFileBuffers (get_io_handle ());
/* FIXME: How to convert UNIX uid/gid to Windows SIDs? */
#if 0 fgei_buf.fgei.NextEntryOffset = 0;
buf->st_uid = nfs_attr->uid; fgei_buf.fgei.EaNameLength = sizeof (NFS_V3_ATTR) - 1;
buf->st_gid = nfs_attr->gid; stpcpy (fgei_buf.fgei.EaName, NFS_V3_ATTR);
#else status = NtQueryEaFile (get_io_handle (), &io,
buf->st_uid = myself->uid; &ffei_buf.ffei, sizeof ffei_buf, TRUE,
buf->st_gid = myself->gid; &fgei_buf.fgei, sizeof fgei_buf, NULL, TRUE);
#endif if (NT_SUCCESS (status))
buf->st_rdev = makedev (nfs_attr->rdev.specdata1, nfs_attr = (fattr3 *) (ffei_buf.ffei.EaName
nfs_attr->rdev.specdata2); + ffei_buf.ffei.EaNameLength + 1);
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;
} }
debug_printf ("%p = NtQueryEaFile(%S)", status, pc.get_nt_native_path ()); buf->st_dev = nfs_attr->fsid;
return -1; 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 int __stdcall

View File

@ -67,7 +67,6 @@
#include "cygtls.h" #include "cygtls.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include "environ.h" #include "environ.h"
#include "nfs.h"
#include <assert.h> #include <assert.h>
#include <ntdll.h> #include <ntdll.h>
#include <wchar.h> #include <wchar.h>
@ -2398,9 +2397,6 @@ restart:
} }
} }
FILE_BASIC_INFORMATION fbi;
PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
if (NT_SUCCESS (status) if (NT_SUCCESS (status)
/* Check file system while we're having the file open anyway. /* Check file system while we're having the file open anyway.
This speeds up path_conv noticably (~10%). */ This speeds up path_conv noticably (~10%). */
@ -2408,17 +2404,34 @@ restart:
{ {
if (fs.is_nfs ()) if (fs.is_nfs ())
{ {
/* NFS doesn't handle FileNetworkOpenInformation when called struct {
via NtQueryInformationFile (STATUS_INVALID_PARAMETER). FILE_FULL_EA_INFORMATION ffei;
Since we only need FileAttributes for NFS anyway, we just char buf[sizeof (NFS_V3_ATTR) + sizeof (fattr3)];
fetch the FileBasicInformation. */ } ffei_buf;
status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, struct {
FileBasicInformation); 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)) 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 else
{ {
PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi, status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
FileNetworkOpenInformation); FileNetworkOpenInformation);
if ((status == STATUS_INVALID_PARAMETER if ((status == STATUS_INVALID_PARAMETER
@ -2428,6 +2441,8 @@ restart:
/* This occurs when accessing SMB share root dirs hosted on /* This occurs when accessing SMB share root dirs hosted on
NT4 (STATUS_INVALID_PARAMETER), or when trying to access NT4 (STATUS_INVALID_PARAMETER), or when trying to access
SMB share root dirs from NT4 (STATUS_NOT_IMPLEMENTED). */ SMB share root dirs from NT4 (STATUS_NOT_IMPLEMENTED). */
FILE_BASIC_INFORMATION fbi;
status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation); FileBasicInformation);
if (NT_SUCCESS (status)) if (NT_SUCCESS (status))
@ -2529,6 +2544,8 @@ restart:
} }
else else
{ {
PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
fileattr = fdi_buf.fdi.FileAttributes; fileattr = fdi_buf.fdi.FileAttributes;
memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi); memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
/* Amazing, but true: The FILE_NETWORK_OPEN_INFORMATION /* Amazing, but true: The FILE_NETWORK_OPEN_INFORMATION
@ -2627,7 +2644,7 @@ restart:
else if (res) else if (res)
{ {
/* A symlink is never a directory. */ /* A symlink is never a directory. */
pfnoi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; conv_hdl.fnoi ()->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
break; break;
} }
} }
@ -2649,7 +2666,7 @@ restart:
/* If the file is on an NFS share and could be opened with extended /* 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 attributes, check if it's a symlink. Only files can be symlinks
(which can be symlinks to directories). */ (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); res = check_nfs_symlink (h);
if (res) if (res)

View File

@ -12,6 +12,7 @@ details. */
#include "devices.h" #include "devices.h"
#include "mount.h" #include "mount.h"
#include "cygheap_malloc.h" #include "cygheap_malloc.h"
#include "nfs.h"
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <fcntl.h> #include <fcntl.h>
@ -96,17 +97,21 @@ class path_conv_handle
{ {
HANDLE hdl; HANDLE hdl;
ACCESS_MASK acc; ACCESS_MASK acc;
/* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in union {
ntdll.h here, though. */ /* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in
struct { ntdll.h here, though. */
LARGE_INTEGER CreationTime; struct {
LARGE_INTEGER LastAccessTime; LARGE_INTEGER CreationTime;
LARGE_INTEGER LastWriteTime; LARGE_INTEGER LastAccessTime;
LARGE_INTEGER ChangeTime; LARGE_INTEGER LastWriteTime;
LARGE_INTEGER AllocationSize; LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize;
ULONG FileAttributes; LARGE_INTEGER EndOfFile;
} _fnoi; ULONG FileAttributes;
} _fnoi;
/* For NFS. */
fattr3 _fattr3;
} attribs;
public: public:
path_conv_handle () : hdl (NULL), acc (0) {} path_conv_handle () : hdl (NULL), acc (0) {}
inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; } inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; }
@ -129,7 +134,9 @@ public:
inline HANDLE handle () const { return hdl; } inline HANDLE handle () const { return hdl; }
inline ACCESS_MASK access () const { return acc; } inline ACCESS_MASK access () const { return acc; }
inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () 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 class path_conv
@ -321,6 +328,7 @@ class path_conv
HANDLE handle () const { return conv_handle.handle (); } HANDLE handle () const { return conv_handle.handle (); }
ACCESS_MASK access () const { return conv_handle.access (); } ACCESS_MASK access () const { return conv_handle.access (); }
struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return conv_handle.fnoi (); } 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 reset_conv_handle () { conv_handle.set (NULL, 0); }
void close_conv_handle () { conv_handle.close (); } void close_conv_handle () { conv_handle.close (); }