Workaround for AFS bug
Francois Gouget
fgouget at codeweavers.com
Mon May 30 05:50:24 CDT 2005
Francois Gouget wrote:
[...]
> So this patch sets d_reclen to 0 before the ioctl() and checks whether
> it's still 0 afterwards.
Setting d_reclen to 0 is tricky because this is also the value which is
returned to signal the EOF. It's ok for the first ioctl() on a directory
(because there's always '.' and '..'), but this is not garanteed in
read_directory_vfat(). If not at the beginning of the directory, then we
cannot determine if d_reclen=0 is because of a legitimate EOF or the AFS
bug.
d_reclen is an unsigned short but cannot have a value greater than 256
because that's the size of the d_name array. So we can detect the AFS
bug more reliably by setting d_reclen to 65535 and checking for a
successful ioctl that leaves it unchanged.
Changelog:
* dlls/ntdll/directory.c
Francois Gouget <fgouget at codeweavers.com>
On some systems (linux 2.6.8) AFS fails to set d_reclen to 0 or does
not support VFAT_IOCTL_READDIR_BOTH but returns 0 (success) anyway. So
set d_reclen to 65535 (an impossible value) before the ioctl() and check
it afterwards to work around this bug.
--
Francois Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: dlls/ntdll/directory.c
===================================================================
RCS file: /var/cvs/wine/dlls/ntdll/directory.c,v
retrieving revision 1.28
diff -u -p -r1.28 directory.c
--- dlls/ntdll/directory.c 20 May 2005 19:24:07 -0000 1.28
+++ dlls/ntdll/directory.c 30 May 2005 10:32:01 -0000
@@ -831,8 +831,12 @@ static int read_directory_vfat( int fd,
{
off_t old_pos = lseek( fd, 0, SEEK_CUR );
+ /* Set d_reclen to 65535 to work around an AFS kernel bug */
+ de[0].d_reclen=65535;
res = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de );
- if (res == -1 && errno != ENOENT) return -1; /* VFAT ioctl probably not supported */
+ if ((res == -1 && errno != ENOENT) ||
+ (res == 0 && de[0].d_reclen == 65535))
+ return -1; /* VFAT ioctl probably not supported */
while (res != -1)
{
@@ -859,8 +863,12 @@ static int read_directory_vfat( int fd,
}
else /* we'll only return full entries, no need to worry about overflow */
{
+ /* Set d_reclen to 65535 to work around an AFS kernel bug */
+ de[0].d_reclen=65535;
res = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de );
- if (res == -1 && errno != ENOENT) return -1; /* VFAT ioctl probably not supported */
+ if ((res == -1 && errno != ENOENT) ||
+ (res == 0 && de[0].d_reclen == 65535))
+ return -1; /* VFAT ioctl probably not supported */
while (res != -1)
{
@@ -1161,7 +1169,10 @@ static NTSTATUS find_file_in_dir( char *
{
KERNEL_DIRENT de[2];
- if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1)
+ /* Set d_reclen to 65535 to work around an AFS kernel bug */
+ de[0].d_reclen=65535;
+ if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1 &&
+ de[0].d_reclen != 65535)
{
unix_name[pos - 1] = '/';
for (;;)
More information about the wine-patches
mailing list