Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-05-21 13:02:42 +0400
committerCorinna Vinschen <corinna@vinschen.de>2008-05-21 13:02:42 +0400
commit0d3f3658816a3759e608d6b944bb22ad194f389c (patch)
tree376fcd68501dae5d7633427c5600cb64962a4fc4
parent2762ac6c1944e320cb880f40866d47475f9892ba (diff)
* fhandler.h (dirent_states): Add dirent_nfs_d_ino state and add it to
dirent_info_mask. * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set dirent_nfs_d_ino flag for NFS shares. Explain why. (fhandler_disk_file::readdir): Use FileNamesInformation instead of FileBothDirectoryInformation info class on NFS clients not supporting the FileIdBothDirectoryInformation info class. Use local pointers to accommodate different offsets. * path.cc (symlink_info::check): Don't test directories for symlinks on NFS shares. Enhance comment.
-rw-r--r--winsup/cygwin/ChangeLog13
-rw-r--r--winsup/cygwin/fhandler.h3
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc39
-rw-r--r--winsup/cygwin/path.cc5
4 files changed, 50 insertions, 10 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 75ce68da4..499495e78 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,18 @@
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
+ * fhandler.h (dirent_states): Add dirent_nfs_d_ino state and add it to
+ dirent_info_mask.
+ * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set
+ dirent_nfs_d_ino flag for NFS shares. Explain why.
+ (fhandler_disk_file::readdir): Use FileNamesInformation instead of
+ FileBothDirectoryInformation info class on NFS clients not supporting
+ the FileIdBothDirectoryInformation info class. Use local pointers to
+ accommodate different offsets.
+ * path.cc (symlink_info::check): Don't test directories for symlinks
+ on NFS shares. Enhance comment.
+
+2008-05-21 Corinna Vinschen <corinna@vinschen.de>
+
* syscalls.cc (FILTERED_MODE): Define valid chmod mode mask.
(chmod): Call fh->fchmod with filtered mode.
(fchmod): Ditto.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 4fe9eade1..82541be6b 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -53,9 +53,10 @@ enum dirent_states
dirent_isroot = 0x0008,
dirent_set_d_ino = 0x0010,
dirent_get_d_ino = 0x0020,
+ dirent_nfs_d_ino = 0x0040,
/* Global flags which must not be deleted on rewinddir or seekdir. */
- dirent_info_mask = 0x0038
+ dirent_info_mask = 0x0078
};
enum conn_state
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 318123903..a8558a700 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1608,12 +1608,21 @@ fhandler_disk_file::opendir (int fd)
OS/FS combinations (say, Win2K/CDFS or so). Instead of
testing in readdir for yet another error code, let's use
FileIdBothDirectoryInformation only on filesystems supporting
- persistent ACLs, FileBothDirectoryInformation otherwise. */
+ persistent ACLs, FileBothDirectoryInformation otherwise.
+
+ On older NFS clients (up to SFU 3.5), dangling symlinks
+ are hidden from directory queries, unless you use the
+ FileNamesInformation info class. Nevertheless, we try
+ FileIdBothDirectoryInformation first. On newer NFS clients
+ it works fine, on the older ones it returns "invalid info
+ class". So we can stick to the above explained mechanism. */
if (pc.hasgood_inode ())
{
dir->__flags |= dirent_set_d_ino;
if (wincap.has_fileid_dirinfo ())
dir->__flags |= dirent_get_d_ino;
+ if (pc.fs_is_nfs ())
+ dir->__flags |= dirent_nfs_d_ino;
}
}
if (fd >= 0)
@@ -1787,6 +1796,8 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
NTSTATUS status = STATUS_SUCCESS;
PFILE_ID_BOTH_DIR_INFORMATION buf = NULL;
PWCHAR FileName;
+ ULONG FileNameLength;
+ ULONG FileAttributes;
IO_STATUS_BLOCK io;
UNICODE_STRING fname;
@@ -1859,7 +1870,9 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
if (!(dir->__flags & dirent_get_d_ino))
status = NtQueryDirectoryFile (get_handle (), NULL, NULL, 0, &io,
d_cache (dir), DIR_BUF_SIZE,
- FileBothDirectoryInformation,
+ (dir->__flags & dirent_nfs_d_ino)
+ ? FileNamesInformation
+ : FileBothDirectoryInformation,
FALSE, NULL, dir->__d_position == 0);
}
@@ -1878,21 +1891,33 @@ go_ahead:
if ((dir->__flags & dirent_get_d_ino))
{
FileName = buf->FileName;
+ FileNameLength = buf->FileNameLength;
+ FileAttributes = buf->FileAttributes;
if ((dir->__flags & dirent_set_d_ino))
de->d_ino = buf->FileId.QuadPart;
}
+ else if ((dir->__flags & dirent_nfs_d_ino))
+ {
+ FileName = ((PFILE_NAMES_INFORMATION) buf)->FileName;
+ FileNameLength = ((PFILE_NAMES_INFORMATION) buf)->FileNameLength;
+ FileAttributes = 0;
+ }
else
- FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
- RtlInitCountedUnicodeString (&fname, FileName, buf->FileNameLength);
+ {
+ FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
+ FileNameLength = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileNameLength;
+ FileAttributes = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileAttributes;
+ }
+ RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{
OBJECT_ATTRIBUTES attr;
- if (dir->__d_position == 0 && buf->FileNameLength == 2
+ if (dir->__d_position == 0 && FileNameLength == 2
&& FileName[0] == '.')
de->d_ino = get_ino_by_handle (get_handle ());
- else if (dir->__d_position == 1 && buf->FileNameLength == 4
+ else if (dir->__d_position == 1 && FileNameLength == 4
&& FileName[0] == L'.' && FileName[1] == L'.')
if (!(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (get_name (), true);
@@ -1922,7 +1947,7 @@ go_ahead:
}
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
- buf ? buf->FileAttributes : 0, &fname)))
+ buf ? FileAttributes : 0, &fname)))
dir->__d_position++;
else if (!(dir->__flags & dirent_saw_dot))
{
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index d01b7f8a2..92994d1b1 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2514,8 +2514,9 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
}
/* If the file could be opened with FILE_READ_EA, and if it's on a
- NFS share, check if it's a symlink. */
- else if (!no_ea && fs.is_nfs ())
+ NFS share, check if it's a symlink. Only files can be symlinks
+ (which can be symlinks to directories). */
+ else if (!no_ea && !(fileattr & FILE_ATTRIBUTE_DIRECTORY) && fs.is_nfs ())
{
res = check_nfs_symlink (h);
if (!res)