* 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.
This commit is contained in:
parent
2762ac6c19
commit
0d3f365881
@ -1,3 +1,16 @@
|
|||||||
|
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>
|
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* syscalls.cc (FILTERED_MODE): Define valid chmod mode mask.
|
* syscalls.cc (FILTERED_MODE): Define valid chmod mode mask.
|
||||||
|
@ -53,9 +53,10 @@ enum dirent_states
|
|||||||
dirent_isroot = 0x0008,
|
dirent_isroot = 0x0008,
|
||||||
dirent_set_d_ino = 0x0010,
|
dirent_set_d_ino = 0x0010,
|
||||||
dirent_get_d_ino = 0x0020,
|
dirent_get_d_ino = 0x0020,
|
||||||
|
dirent_nfs_d_ino = 0x0040,
|
||||||
|
|
||||||
/* Global flags which must not be deleted on rewinddir or seekdir. */
|
/* Global flags which must not be deleted on rewinddir or seekdir. */
|
||||||
dirent_info_mask = 0x0038
|
dirent_info_mask = 0x0078
|
||||||
};
|
};
|
||||||
|
|
||||||
enum conn_state
|
enum conn_state
|
||||||
|
@ -1608,12 +1608,21 @@ fhandler_disk_file::opendir (int fd)
|
|||||||
OS/FS combinations (say, Win2K/CDFS or so). Instead of
|
OS/FS combinations (say, Win2K/CDFS or so). Instead of
|
||||||
testing in readdir for yet another error code, let's use
|
testing in readdir for yet another error code, let's use
|
||||||
FileIdBothDirectoryInformation only on filesystems supporting
|
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 ())
|
if (pc.hasgood_inode ())
|
||||||
{
|
{
|
||||||
dir->__flags |= dirent_set_d_ino;
|
dir->__flags |= dirent_set_d_ino;
|
||||||
if (wincap.has_fileid_dirinfo ())
|
if (wincap.has_fileid_dirinfo ())
|
||||||
dir->__flags |= dirent_get_d_ino;
|
dir->__flags |= dirent_get_d_ino;
|
||||||
|
if (pc.fs_is_nfs ())
|
||||||
|
dir->__flags |= dirent_nfs_d_ino;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
@ -1787,6 +1796,8 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
|
|||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
PFILE_ID_BOTH_DIR_INFORMATION buf = NULL;
|
PFILE_ID_BOTH_DIR_INFORMATION buf = NULL;
|
||||||
PWCHAR FileName;
|
PWCHAR FileName;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
ULONG FileAttributes;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
UNICODE_STRING fname;
|
UNICODE_STRING fname;
|
||||||
|
|
||||||
@ -1859,7 +1870,9 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
|
|||||||
if (!(dir->__flags & dirent_get_d_ino))
|
if (!(dir->__flags & dirent_get_d_ino))
|
||||||
status = NtQueryDirectoryFile (get_handle (), NULL, NULL, 0, &io,
|
status = NtQueryDirectoryFile (get_handle (), NULL, NULL, 0, &io,
|
||||||
d_cache (dir), DIR_BUF_SIZE,
|
d_cache (dir), DIR_BUF_SIZE,
|
||||||
FileBothDirectoryInformation,
|
(dir->__flags & dirent_nfs_d_ino)
|
||||||
|
? FileNamesInformation
|
||||||
|
: FileBothDirectoryInformation,
|
||||||
FALSE, NULL, dir->__d_position == 0);
|
FALSE, NULL, dir->__d_position == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1878,21 +1891,33 @@ go_ahead:
|
|||||||
if ((dir->__flags & dirent_get_d_ino))
|
if ((dir->__flags & dirent_get_d_ino))
|
||||||
{
|
{
|
||||||
FileName = buf->FileName;
|
FileName = buf->FileName;
|
||||||
|
FileNameLength = buf->FileNameLength;
|
||||||
|
FileAttributes = buf->FileAttributes;
|
||||||
if ((dir->__flags & dirent_set_d_ino))
|
if ((dir->__flags & dirent_set_d_ino))
|
||||||
de->d_ino = buf->FileId.QuadPart;
|
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
|
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);
|
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
|
||||||
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
|
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
|
||||||
if (dir->__d_position == 0 && buf->FileNameLength == 2
|
if (dir->__d_position == 0 && FileNameLength == 2
|
||||||
&& FileName[0] == '.')
|
&& FileName[0] == '.')
|
||||||
de->d_ino = get_ino_by_handle (get_handle ());
|
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'.')
|
&& FileName[0] == L'.' && FileName[1] == L'.')
|
||||||
if (!(dir->__flags & dirent_isroot))
|
if (!(dir->__flags & dirent_isroot))
|
||||||
de->d_ino = readdir_get_ino (get_name (), true);
|
de->d_ino = readdir_get_ino (get_name (), true);
|
||||||
@ -1922,7 +1947,7 @@ go_ahead:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
|
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
|
||||||
buf ? buf->FileAttributes : 0, &fname)))
|
buf ? FileAttributes : 0, &fname)))
|
||||||
dir->__d_position++;
|
dir->__d_position++;
|
||||||
else if (!(dir->__flags & dirent_saw_dot))
|
else if (!(dir->__flags & dirent_saw_dot))
|
||||||
{
|
{
|
||||||
|
@ -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
|
/* If the file could be opened with FILE_READ_EA, and if it's on a
|
||||||
NFS share, check if it's a symlink. */
|
NFS share, check if it's a symlink. Only files can be symlinks
|
||||||
else if (!no_ea && fs.is_nfs ())
|
(which can be symlinks to directories). */
|
||||||
|
else if (!no_ea && !(fileattr & FILE_ATTRIBUTE_DIRECTORY) && fs.is_nfs ())
|
||||||
{
|
{
|
||||||
res = check_nfs_symlink (h);
|
res = check_nfs_symlink (h);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user