Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
006413af
Commit
006413af
authored
Aug 04, 2011
by
Grazvydas Ignotas
Committed by
Alexandre Julliard
Aug 24, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Use swapping method to return . and .. as first entries.
parent
fbf537fb
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
91 additions
and
54 deletions
+91
-54
directory.c
dlls/ntdll/directory.c
+88
-44
directory.c
dlls/ntdll/tests/directory.c
+3
-10
No files found.
dlls/ntdll/directory.c
View file @
006413af
...
...
@@ -1486,22 +1486,56 @@ static int read_directory_vfat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
#endif
/* VFAT_IOCTL_READDIR_BOTH */
#ifdef USE_GETDENTS
/***********************************************************************
* read_first_dent_name
*
* reads name of first or second dentry (if they have inodes).
*/
static
char
*
read_first_dent_name
(
int
which
,
int
fd
,
off_t
second_offs
,
KERNEL_DIRENT64
*
de_first_two
,
char
*
buffer
,
size_t
size
,
BOOL
*
buffer_changed
)
{
KERNEL_DIRENT64
*
de
;
int
res
;
de
=
de_first_two
;
if
(
de
!=
NULL
)
{
if
(
which
==
1
)
de
=
(
KERNEL_DIRENT64
*
)((
char
*
)
de
+
de
->
d_reclen
);
return
de
->
d_ino
?
de
->
d_name
:
NULL
;
}
*
buffer_changed
=
TRUE
;
lseek
(
fd
,
which
==
1
?
second_offs
:
0
,
SEEK_SET
);
res
=
getdents64
(
fd
,
buffer
,
size
);
if
(
res
<=
0
)
return
NULL
;
de
=
(
KERNEL_DIRENT64
*
)
buffer
;
return
de
->
d_ino
?
de
->
d_name
:
NULL
;
}
/***********************************************************************
* read_directory_getdents
*
* Read a directory using the Linux getdents64 system call; helper for NtQueryDirectoryFile.
*/
#ifdef USE_GETDENTS
static
int
read_directory_getdents
(
int
fd
,
IO_STATUS_BLOCK
*
io
,
void
*
buffer
,
ULONG
length
,
BOOLEAN
single_entry
,
const
UNICODE_STRING
*
mask
,
BOOLEAN
restart_scan
,
FILE_INFORMATION_CLASS
class
)
{
off_t
old_pos
=
0
;
static
off_t
second_entry_pos
;
static
struct
file_identity
last_dir_id
;
off_t
old_pos
=
0
,
next_pos
;
size_t
size
=
length
;
int
res
,
fake_dot_dot
=
1
;
char
*
data
,
local_buffer
[
8192
];
KERNEL_DIRENT64
*
de
;
KERNEL_DIRENT64
*
de
,
*
de_first_two
=
NULL
;
union
file_directory_info
*
info
,
*
last_info
=
NULL
;
const
char
*
filename
;
BOOL
data_buffer_changed
;
int
res
,
swap_to
;
if
(
size
<=
sizeof
(
local_buffer
)
||
!
(
data
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
size
)))
{
...
...
@@ -1510,7 +1544,7 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
}
if
(
restart_scan
)
lseek
(
fd
,
0
,
SEEK_SET
);
else
if
(
length
<
max_dir_info_size
(
class
))
/* we may have to return a partial entry here */
else
{
old_pos
=
lseek
(
fd
,
0
,
SEEK_CUR
);
if
(
old_pos
==
-
1
&&
errno
==
ENOENT
)
...
...
@@ -1522,6 +1556,21 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
}
io
->
u
.
Status
=
STATUS_SUCCESS
;
de
=
(
KERNEL_DIRENT64
*
)
data
;
/* if old_pos is not 0 we don't know how many entries have been returned already,
* so maintain second_entry_pos to know when to return '..' */
if
(
old_pos
!=
0
&&
(
last_dir_id
.
dev
!=
curdir
.
dev
||
last_dir_id
.
ino
!=
curdir
.
ino
))
{
lseek
(
fd
,
0
,
SEEK_SET
);
res
=
getdents64
(
fd
,
data
,
size
);
if
(
res
>
0
)
{
second_entry_pos
=
de
->
d_off
;
last_dir_id
=
curdir
;
}
lseek
(
fd
,
old_pos
,
SEEK_SET
);
}
res
=
getdents64
(
fd
,
data
,
size
);
if
(
res
==
-
1
)
...
...
@@ -1534,52 +1583,46 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
goto
done
;
}
de
=
(
KERNEL_DIRENT64
*
)
data
;
if
(
old_pos
==
0
&&
res
>
0
)
{
second_entry_pos
=
de
->
d_off
;
last_dir_id
=
curdir
;
if
(
res
>
de
->
d_reclen
)
de_first_two
=
de
;
}
if
(
restart_scan
)
while
(
res
>
0
)
{
/* check if we got . and .. from getdents */
if
(
res
>
0
)
{
if
(
!
strcmp
(
de
->
d_name
,
"."
)
&&
res
>
de
->
d_reclen
)
{
KERNEL_DIRENT64
*
next_de
=
(
KERNEL_DIRENT64
*
)(
data
+
de
->
d_reclen
);
if
(
!
strcmp
(
next_de
->
d_name
,
".."
))
fake_dot_dot
=
0
;
}
}
/* make sure we have enough room for both entries */
if
(
fake_dot_dot
)
{
const
ULONG
min_info_size
=
dir_info_size
(
class
,
1
)
+
dir_info_size
(
class
,
2
);
if
(
length
<
min_info_size
||
single_entry
)
{
FIXME
(
"not enough room %u/%u for fake . and .. entries
\n
"
,
length
,
single_entry
);
fake_dot_dot
=
0
;
}
}
res
-=
de
->
d_reclen
;
next_pos
=
de
->
d_off
;
filename
=
NULL
;
if
(
fake_dot_dot
)
/* we must return first 2 entries as "." and "..", but getdents64()
* can return them anywhere, so swap first entries with "." and ".." */
if
(
old_pos
==
0
)
filename
=
"."
;
else
if
(
old_pos
==
second_entry_pos
)
filename
=
".."
;
else
if
(
!
strcmp
(
de
->
d_name
,
"."
)
||
!
strcmp
(
de
->
d_name
,
".."
))
{
if
((
info
=
append_entry
(
buffer
,
io
,
length
,
"."
,
NULL
,
mask
,
class
)))
last_info
=
info
;
if
((
info
=
append_entry
(
buffer
,
io
,
length
,
".."
,
NULL
,
mask
,
class
)))
last_info
=
info
;
/* check if we still have enough space for the largest possible entry */
if
(
last_info
&&
io
->
Information
+
max_dir_info_size
(
class
)
>
length
)
swap_to
=
!
strcmp
(
de
->
d_name
,
"."
)
?
0
:
1
;
data_buffer_changed
=
FALSE
;
filename
=
read_first_dent_name
(
swap_to
,
fd
,
second_entry_pos
,
de_first_two
,
data
,
size
,
&
data_buffer_changed
);
if
(
filename
!=
NULL
&&
(
!
strcmp
(
filename
,
"."
)
||
!
strcmp
(
filename
,
".."
)))
filename
=
read_first_dent_name
(
swap_to
^
1
,
fd
,
second_entry_pos
,
NULL
,
data
,
size
,
&
data_buffer_changed
);
if
(
data_buffer_changed
)
{
lseek
(
fd
,
0
,
SEEK_SET
);
/* reset pos to first entry */
lseek
(
fd
,
next_pos
,
SEEK_SET
);
res
=
0
;
}
}
}
else
if
(
de
->
d_ino
)
filename
=
de
->
d_name
;
while
(
res
>
0
)
{
res
-=
de
->
d_reclen
;
if
(
de
->
d_ino
&&
!
(
fake_dot_dot
&&
(
!
strcmp
(
de
->
d_name
,
"."
)
||
!
strcmp
(
de
->
d_name
,
".."
)))
&&
(
info
=
append_entry
(
buffer
,
io
,
length
,
de
->
d_name
,
NULL
,
mask
,
class
)))
if
(
filename
&&
(
info
=
append_entry
(
buffer
,
io
,
length
,
filename
,
NULL
,
mask
,
class
)))
{
last_info
=
info
;
if
(
io
->
u
.
Status
==
STATUS_BUFFER_OVERFLOW
)
...
...
@@ -1590,17 +1633,18 @@ static int read_directory_getdents( int fd, IO_STATUS_BLOCK *io, void *buffer, U
/* check if we still have enough space for the largest possible entry */
if
(
single_entry
||
io
->
Information
+
max_dir_info_size
(
class
)
>
length
)
{
if
(
res
>
0
)
lseek
(
fd
,
de
->
d_off
,
SEEK_SET
);
/* set pos to next entry */
if
(
res
>
0
)
lseek
(
fd
,
next_pos
,
SEEK_SET
);
/* set pos to next entry */
break
;
}
}
old_pos
=
de
->
d_off
;
old_pos
=
next_pos
;
/* move on to the next entry */
if
(
res
>
0
)
de
=
(
KERNEL_DIRENT64
*
)((
char
*
)
de
+
de
->
d_reclen
);
else
{
res
=
getdents64
(
fd
,
data
,
size
);
de
=
(
KERNEL_DIRENT64
*
)
data
;
de_first_two
=
NULL
;
}
}
...
...
dlls/ntdll/tests/directory.c
View file @
006413af
...
...
@@ -215,16 +215,9 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
}
ok
(
numfiles
<
max_test_dir_size
,
"too many loops
\n
"
);
for
(
i
=
0
;
testfiles
[
i
].
name
;
i
++
)
{
if
((
strcmp
(
testfiles
[
i
].
name
,
"."
)
==
0
||
strcmp
(
testfiles
[
i
].
name
,
".."
)
==
0
)
&&
(
single_entry
||
!
restart_flag
))
{
todo_wine
ok
(
testfiles
[
i
].
nfound
==
1
,
"Wrong number %d of %s files found (ReturnSingleEntry=%d,RestartScan=%d)
\n
"
,
testfiles
[
i
].
nfound
,
testfiles
[
i
].
description
,
single_entry
,
restart_flag
);
}
else
{
ok
(
testfiles
[
i
].
nfound
==
1
,
"Wrong number %d of %s files found (ReturnSingleEntry=%d,RestartScan=%d)
\n
"
,
testfiles
[
i
].
nfound
,
testfiles
[
i
].
description
,
single_entry
,
restart_flag
);
}
}
for
(
i
=
0
;
testfiles
[
i
].
name
;
i
++
)
ok
(
testfiles
[
i
].
nfound
==
1
,
"Wrong number %d of %s files found (ReturnSingleEntry=%d,RestartScan=%d)
\n
"
,
testfiles
[
i
].
nfound
,
testfiles
[
i
].
description
,
single_entry
,
restart_flag
);
pNtClose
(
dirh
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment