dokan-dev / dokany

User mode file system library for windows with FUSE Wrapper
http://dokan-dev.github.io
5.21k stars 661 forks source link

NO_SUCH_FILE returned on listing empty root directory #1077

Closed infeo closed 2 years ago

infeo commented 2 years ago

Environment

Check List

Description

Dokany does not require to implement all dokan operations in order to work as intended. In my case, i created a (memory-only) filesystem only implementing zwCreateFile, cleanup, closeFile and findFiles. It seems to work, but if I start a listing on the empty directory root, instead of STATUS_SUCCESS always STATUS_NO_SUCH_FILE is returned.

Looking into Dokany Code, of interest is directory.c: https://github.com/dokan-dev/dokany/blob/1ffacd40d6ca402c2b49aec2b6fdddfa1a668fa6/dokan/directory.c#L518-L530

Here the return code will be changed from whatever is returned by the developer fs to NO_SUCH_FILE, if there is no matching entry in the listing and the directory file index is 0. From my naive point of view, this is somewhat inconsistent, because if the file index is 0 but there is a match, we do not change the NTStatus. What is the file index, and why are we doing this check?

Logs

-/-

Liryna commented 2 years ago

For FileIndex See https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/flt-parameters-for-irp-mj-directory-control

Index of the file where the directory scan begins. Ignored if the SL_INDEX_SPECIFIED flag is not set. This parameter cannot be specified in any Win32 function or kernel-mode support routine. Currently it is used only by the NT virtual DOS machine (NTVDM), which exists only on 32-bit NT-based operating systems. Note that the file index is undefined for file systems, such as NTFS, in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.

FileIndex is 0 at the first call to inform the FS the listing start from the beginning. Since the kernel buffer might not have the space to list everything, the kernel will issue a new listing with the index increased prior to the previous call. So if FileIndex is 0 and there is not match (findfileswithpattern), we return STATUS_NO_SUCH_FILE instead of STATUS_NO_MORE_FILES when we would have already returned matching items previously.

because if the file index is 0 but there is a match

MatchFiles returns a negative value when there is no match. What do you mean exactly ?

infeo commented 2 years ago

Just to prevent confusion: In my filesystem

From a non-dokany developer perspective, this does not make sense, because the root dir is, well, just another directory.

Since the kernel buffer might not have the space to list everything,

If the directory is empty, the kernel buffer can't have not enough space.

MatchFiles returns a negative value when there is no match. What do you mean exactly ?

This is very likely a lack of knowledge on my site: If we have a matching entry, we do not seem to care about the value of Directory.FileIndex. So why do we care about it, if there is no match (or when the listing is empty)?

infeo commented 2 years ago

Ohhkay, maybe this is a Windows thing. Out of curiosity, created an empty drive letter and listed the content of the drive letter:

I:\>dir
 Volume in drive I is New Volume
 Volume Serial Number is E094-3BAA

 Directory of I:\

File Not Found

So I guess returning "Not found" is expected behaviour?

Liryna commented 2 years ago

Indeed the root directory does not have a . and .. compared to sub dir. We even populate them if the user fs did not https://github.com/dokan-dev/dokany/blob/1ffacd40d6ca402c2b49aec2b6fdddfa1a668fa6/dokan/directory.c#L565

You can use Procmon to see and compare the different status return on dokan & other drive.

How FileIndex work ? Lets say you have this folder content:

- foo.txt
- bar.txt
- ball.txt

So why do we care about it, if there is no match (or when the listing is empty)?

If FileIndex is not 0, it means we answered a previous listing with matching files and Kernel is asking for the remaining one. If we listed everything already, we return STATUS_NO_MORE_FILES. I would expect this not to happen since we should have returned a STATUS_SUCCESS at the first request and not a STATUS_BUFFER_OVERFLOW that would make kernel fetch new one.

infeo commented 2 years ago

Ah, I see. Thank you for the detailed explanation.

But this only works, if the implemented filesystem lists resources deterministically, right? The microsoft documention already says:

Note that the file index is undefined for file systems, such as NTFS, in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.

Can Dokany cope with that?

Liryna commented 2 years ago

Yes it does since v2! 💪 After listing we cache the result in the library by using the memory pool https://github.com/dokan-dev/dokany/blob/1ffacd40d6ca402c2b49aec2b6fdddfa1a668fa6/dokan/directory.c#L571 to use the same dir list result when kernel continue the process https://github.com/dokan-dev/dokany/blob/1ffacd40d6ca402c2b49aec2b6fdddfa1a668fa6/dokan/directory.c#L674-L676

infeo commented 2 years ago

Wow, that is indeed a cool feature.

Thanks again for all the infos, my question(s) are now sufficently answered. 🙂