-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to specify files inode #196
Comments
Just looked over it and found that FileName in FileInformation at that place isn't needed at all. It's just used to generate the hash and nothing else. The same entry in the same struct stands for FileName everywhere else. And is also called |
Hi @dedmen ,
Which description do you think you would have like here ? |
I'd say use a new struct that has the actual INODE handle as a number instead of That change would be a API breaking change. |
Hi @dedmen , I agree with your proposition. Do you think you could provide a pull request with the changes ? This would be greatly appreciated 👍 |
Yeah sure. Probably next weekend |
@dedmen I imagine next weekend is far enough now 😄 just wanted to know if it is really out of your time ? |
Sorry, I spent most of my time on other projects as the dokan thing was working well enough at that point. This is still on my todo list, but not a high priority sadly. Too much other stuff going on. |
No worry 👍 Thank you for the update and the workaround that might help others ! |
For reference (as I already forgot most of the stuff I was looking at back then) Hash is calculated and used here: dokan-dotnet/DokanNet/DokanOperationProxy.cs Line 547 in fa556df
This dokan-dotnet/DokanNet/DokanOperationProxy.cs Line 515 in fa556df
should really just return a struct mirroring the BY_HANDLE_FILE_INFORMATION contents in a C# format, we can basically keep most things but just add 64bit(?) number for fileIndex (inode) and dwNumberOfLinks
We need to communicate a way to the users to still let them generate hash from filename, to make sure new users won't be confused? |
Exactly, we should use another struct having FileIndex that user can set OR let equal to 0 and dokan-dotnet handle it by keeping a hashmap updated with FileIndex of each file and cleanup when all handles are closed. There is no real rules for FileIndex even if the best would be to duplicate NTFS @dedmen just to come back at what you said. When you copied the file to another folder you said |
correct. Full path would work. As thats my workaround. |
I might have missed something. For me |
Atleast I think thats the case. FindFiles in C API uses dokan-dotnet/DokanNet/DokanOperationProxy.cs Line 681 in fa556df
On the other hand all the dokan methods take a "filename" as argument which is really a fullpath. FindStreams returns So I guess I also kinda missinterpreted the API due to the mix of filename vs fullpath. https://dokan-dev.github.io/dokan-dotnet-doc/html/struct_dokan_net_1_1_file_information.html
|
I agree, the documentation should be improved Regarding the main reason of this issue, we agree that only Can we agree to focus on changing the API ? We could just do struct inheritance as they look the same and change the API to use, as you proposed, the correct member names. |
Technically yes.. but it's more a hacky workaround than a real solution. And it requires the user to read the documentation instead of just relying on the filename. And then we have still the issue that the user used filename for the other variants and it worked fine, so he assumes he has to do the same in GetFileInformation too.
We only let the user access 32bit, of the 64bit value. User might want access the rest too.
As I said, I would just split the "FileInformation" struct, into 3 (FindFiles, FindStreams, GetFileInformation) seperate structs, that expose exactly the value that are actually needed. dokan-dotnet/DokanNet/FileInformation.cs Lines 10 to 13 in 3b70a57
FindFiles (both variants) needs to contain everything that FileInformation had. And we can keep "FileName" as that matches Win32 API. FindStreams needs dokan-dotnet/DokanNet/DokanOperationProxy.cs Lines 749 to 753 in fa556df
GetFileInformation needs dokan-dotnet/DokanNet/DokanOperationProxy.cs Line 505 in fa556df
We could do inheritance and just define properly named get/set and pass the same base-struct in the backend if that makes things easier, but I wouldn't know why also I'd prefer not to allocate/copy large structs, where 80% of the content is unused. |
@dedmen I fully agree on changing the API to use the struct inheritance. Do you think you would be able to provide a PR for it ? |
Able of course :D |
@dedmen Great ! :) No deadline at all, of course (this is opensource :D) ! SI'm sorry if I sounded like I was pushing ^^ |
...this is an entire thing, just because Python's Windows simply doesn't have the concept of an inode, nor a native concept of two directory entries that directly point to the same file (clusters). As such, on Windows NTFS, there is no possible way that two named regular files (i.e., files that are not reparse points) can ever possibly be the same underlying file object. The only instances where they could appear to be are under the old Single Instance Storage driver (which was a thing on Windows 2000 Server's Remote Installation Service), which relied on reparse points... and symlinks or hardlinks, which are also implemented as reparse points. (Notably, neither the SIS nor symlink/hardlink functionality ever require the names to match across all locations, so Python's It doesn't make sense to try to address that bug here. It's a bug in Python that Python needs to deal with. Also, my thinking is that the most appropriate mapping of the inode concept to Windows would be through the "object ID" mechanism (ntifs.h:NtCreateFile's |
This is not only a thing because of that python bug. I'd like to specify the id by myself too, and sending a string who'se whole purpose is to generate a ID is counterintuitive. |
I have my own reasons for wanting to specify the ID, for FILE_OPEN_BY_FILE_ID handling. I honestly think it'd be most appropriate to address this bug by implementing that. That said... all filenames that come to the functions pointed to in DOKAN_OPERATIONS from dokan1.sys are (currently) passed the full pathname within the filesystem. There's no "look for current working directory and append the filename to it" that the filesystem implementation needs to do, it's all handled by the driver. Which is good, because the driver doesn't pass current working directory information to the implementation. I don't think the driver can actually even get the current working directory information of the process that called it. To understand BY_HANDLE_FILE_INFORMATION and its use of nFileIndexLow and nFileIndexHigh, it's important to realize that those came directly from the definition in the NT header files. Those fields are expressly defined and populated to support FILE_OPEN_BY_FILE_ID. The fact that you want to specify them is awesome, and I wholeheartedly salute it -- I just want it done correctly. If FILE_OPEN_BY_FILE_ID is handled, the file ID is passed to the kernel in raw form (64 raw bits, with no base64 encoding, no padding, no NUL-termination) as FileName. Trying to interpret it as a string will either lead to incorrect behavior (since the first four bytes of a 32 bit value stuffed into a 64-bit space matches the UTF-32 representation of U+0000, thus leading to a string that's empty) or a bluescreen (since a 64-bit number with no 0x00 octets would have no guarantee that it would be followed by U+0000 in any reasonable space, and the kernel driver would need to interpret it as a string to determine what filename to pass up to user mode) -- see https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntcreatefile for more information. But, since the kernel driver would also receive the FILE_OPEN_BY_FILE_ID flag, it would be easy enough for the driver to break the value out into the nFileIndexLow and nFileIndexHigh fields, and pass an empty string in FileName. (This would be the differentiation that would allow a user to know that it's being requested to open a file by ID instead of by name -- if the string is As an implementation note on your patch, I'd also suggest making that parameter I understand that you probably derived the name Also, the name that NtCreateFile receives when asked to open by FILE_ID is of either of the forms |
This code
https://github.com/dokan-dev/dokan-dotnet/blob/master/DokanNet/DokanOperationProxy.cs#L507
Causes the inode for two completly different files to be the same if they just have the same filename.
I'm running Python scripts that copy files around on my drive.
And python's
os.path.samefile
checks if the file's inode and deviceID are different. Which they aren't if the files happen to have the same name.In my case I am trying to copy a file to a different directory. So it indeed has the same name and thus the same inode. But they are still seperate files.
My proposed solution would be to provide the ability to set the inode in the FileInformation struct but keep it optional.
What could be done is have JUST
GetFileInformation
return a different FileInformation struct than everywhere else which contains the full path instead of just the filename.In my case I'm storing the FileInformation struct directly in my file node because I don't need to generate a new one everytime.
Instead of
I would need to
But that would make
GetFileInformation
from now on always return a wrong FileName.Which is btw what the Mirror sample is already doing.
The text was updated successfully, but these errors were encountered: