* fhandler.cc (fhandler_base::open): Always open NFS files with

FILE_READ_EA, even when opening with O_WRONLY to allow fstat.
	* fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Call
	FlushFileBuffers if file has been opened for writing.  Explain why.
	(fhandler_base::fstat_by_handle): Renew content of pc.fnoi if called
	via fstat.  Explain why.  Fix formatting.
	* path.cc (symlink_info::check): Try to open file the second time with
	FILE_READ_EA permissions since it's needed in later calls to
	fhandler_base::fstat_by_nfs_ea.
This commit is contained in:
Corinna Vinschen 2010-09-21 16:07:20 +00:00
parent 6fb0ddfe34
commit 7ba1698ed9
4 changed files with 52 additions and 11 deletions

View File

@ -1,3 +1,15 @@
2010-09-21 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base::open): Always open NFS files with
FILE_READ_EA, even when opening with O_WRONLY to allow fstat.
* fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Call
FlushFileBuffers if file has been opened for writing. Explain why.
(fhandler_base::fstat_by_handle): Renew content of pc.fnoi if called
via fstat. Explain why. Fix formatting.
* path.cc (symlink_info::check): Try to open file the second time with
FILE_READ_EA permissions since it's needed in later calls to
fhandler_base::fstat_by_nfs_ea.
2010-09-20 Christopher Faylor <me+cygwin@cgf.cx>
* include/sys/cygwin.h (PID_NOTCYGWIN): New enum.

View File

@ -501,16 +501,19 @@ fhandler_base::open (int flags, mode_t mode)
break;
}
if (query_open () && pc.fs_is_nfs ())
if (pc.fs_is_nfs ())
{
/* Make sure we can read EAs of files on an NFS share. Also make
sure that we're going to act on the file itself, even if it'a
sure that we're going to act on the file itself, even if it's a
a symlink. */
access |= FILE_READ_EA;
if (query_open () >= query_write_control)
access |= FILE_WRITE_EA;
plen = sizeof nfs_aol_ffei;
p = (PFILE_FULL_EA_INFORMATION) &nfs_aol_ffei;
if (query_open ())
{
if (query_open () >= query_write_control)
access |= FILE_WRITE_EA;
plen = sizeof nfs_aol_ffei;
p = (PFILE_FULL_EA_INFORMATION) &nfs_aol_ffei;
}
}
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))

View File

@ -305,6 +305,14 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf)
char buf[sizeof (NFS_V3_ATTR)];
} fgei_buf;
/* 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);
@ -356,6 +364,21 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
NTSTATUS status = 0;
IO_STATUS_BLOCK io;
/* If the file has been opened for other purposes than stat, we can't rely
on the information stored in pc.fnoi. So we overwrite them here. */
if (get_io_handle ())
{
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
FileNetworkOpenInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile(%S, "
"FileNetworkOpenInformation)",
status, pc.get_nt_native_path ());
return -1;
}
}
if (!pc.hasgood_inode ())
fsi.NumberOfLinks = 1;
else
@ -364,7 +387,8 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
FileStandardInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile(%S, FileStandardInformation)",
debug_printf ("%p = NtQueryInformationFile(%S, "
"FileStandardInformation)",
status, pc.get_nt_native_path ());
return -1;
}
@ -374,7 +398,8 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
FileInternalInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile(%S, FileInternalInformation)",
debug_printf ("%p = NtQueryInformationFile(%S, "
"FileInternalInformation)",
status, pc.get_nt_native_path ());
return -1;
}

View File

@ -2296,10 +2296,11 @@ restart:
FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT,
eabuf, easize);
if (status == STATUS_ACCESS_DENIED)
if (status == STATUS_ACCESS_DENIED && eabuf)
{
status = NtCreateFile (&h, access = MIN_STAT_ACCESS, &attr, &io,
NULL, 0, FILE_SHARE_VALID_FLAGS, FILE_OPEN,
status = NtCreateFile (&h, access = MIN_STAT_ACCESS | FILE_READ_EA,
&attr, &io, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN,
FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT,
eabuf, easize);