problem reading dir's with fix
Rein Klazes
wijn at wanadoo.nl
Thu Dec 9 07:38:37 CST 2004
hi,
Since the change from readdir to getdents64 I cannot access certain
files and dir's (including the one used for saving wine patches) with
the common file dialog's.
| 0009:Call ntdll.NtQueryDirectoryFile(00000010,00000000,00000000,00000000,77a6a070,77cc6b24,00002000,00000003,00000000,77cc6b10,00000000) ret=77b26174
| trace:file:NtQueryDirectoryFile (0x10 (nil) (nil) (nil) 0x77a6a070 0x77cc6b24 0x00002000 0x00000003 0x00000000 L"diffs" 0x00000000
| trace:file:append_entry long L"."... short L""... mask L"diffs"
| trace:file:match_filename (L"."..., L"diffs")
| trace:file:append_entry long L".."... short L""... mask L"diffs"
| trace:file:match_filename (L".."..., L"diffs")
[some 200 entries snipped]
| trace:file:append_entry long L"freecell.ICO"... short L""... mask L"diffs"
| trace:file:match_filename (L"freecell.ICO"..., L"diffs")
| trace:file:NtQueryDirectoryFile => 80000006 (0)
| 0009:Ret ntdll.NtQueryDirectoryFile() retval=80000006 ret=77b26174
| 0009:Call ntdll.RtlNtStatusToDosError(80000006) ret=77b261e1
| 0009:Ret ntdll.RtlNtStatusToDosError() retval=00000012 ret=77b261e1
| trace:file:FindFirstFileExW L"H:\\diffs" not found
H:\ contains almost 400 entries, so it is clear not all are read.
Looking through the code I notice that getdents64 is called only once,
where readdir was called several times.
Here is my solution that fixes the problem for me.
Changelog:
dlls/ntdll : directory.c
If needed, keep calling getdents64() until no more entries are
returned.
Rein.
-------------- next part --------------
--- wine/dlls/ntdll/directory.c 2004-12-08 08:50:24.000000000 +0100
+++ mywine/dlls/ntdll/directory.c 2004-12-09 14:21:15.000000000 +0100
@@ -753,54 +753,57 @@ static int read_directory_getdents( int
{
io->u.Status = STATUS_NO_MORE_FILES;
res = 0;
- goto done;
+ goto done_2;
}
}
io->u.Status = STATUS_SUCCESS;
-
- res = getdents64( fd, data, size );
- if (res == -1)
- {
- if (errno != ENOSYS)
+ while(1) {
+ res = getdents64( fd, data, size );
+ if (res == -1)
{
- io->u.Status = FILE_GetNtStatus();
- res = 0;
+ if (errno != ENOSYS)
+ {
+ io->u.Status = FILE_GetNtStatus();
+ res = 0;
+ }
+ goto done_2;
}
- goto done;
- }
+ if( !res) break;
- de = data;
+ de = data;
- while (res > 0)
- {
- res -= de->d_reclen;
- info = append_entry( buffer, &io->Information, length, de->d_name, NULL, mask );
- if (info)
+ while (res > 0)
{
- last_info = info;
- if ((char *)info->FileName + info->FileNameLength > (char *)buffer + length)
- {
- io->u.Status = STATUS_BUFFER_OVERFLOW;
- lseek( fd, old_pos, SEEK_SET ); /* restore pos to previous entry */
- break;
- }
- /* check if we still have enough space for the largest possible entry */
- if (single_entry || io->Information + max_dir_info_size > length)
+ res -= de->d_reclen;
+ info = append_entry( buffer, &io->Information, length, de->d_name, NULL, mask );
+ if (info)
{
- if (res > 0) lseek( fd, de->d_off, SEEK_SET ); /* set pos to next entry */
- break;
+ last_info = info;
+ if ((char *)info->FileName + info->FileNameLength > (char *)buffer + length)
+ {
+ io->u.Status = STATUS_BUFFER_OVERFLOW;
+ lseek( fd, old_pos, SEEK_SET ); /* restore pos to previous entry */
+ goto done_1;
+ }
+ /* check if we still have enough space for the largest possible entry */
+ if (single_entry || io->Information + max_dir_info_size > length)
+ {
+ if (res > 0) lseek( fd, de->d_off, SEEK_SET ); /* set pos to next entry */
+ goto done_1;
+ }
}
+ old_pos = de->d_off;
+ /* move on to the next entry */
+ de = (KERNEL_DIRENT64 *)((char *)de + de->d_reclen);
}
- old_pos = de->d_off;
- /* move on to the next entry */
- de = (KERNEL_DIRENT64 *)((char *)de + de->d_reclen);
}
+done_1:
if (last_info) last_info->NextEntryOffset = 0;
else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
res = 0;
-done:
+done_2:
if ((char *)data != local_buffer) RtlFreeHeap( GetProcessHeap(), 0, data );
return res;
}
More information about the wine-devel
mailing list