Skip to content
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

Enabling case sensitive paths in registry sometimes breaks flinux #58

Closed
Sh4rK opened this issue Sep 4, 2015 · 8 comments · Fixed by #67
Closed

Enabling case sensitive paths in registry sometimes breaks flinux #58

Sh4rK opened this issue Sep 4, 2015 · 8 comments · Fixed by #67
Labels

Comments

@Sh4rK
Copy link
Contributor

Sh4rK commented Sep 4, 2015

I discovered that by default, even if you use NtCreateFile and friends without OBJ_CASE_INSENSITIVE, file handling is case insensitive in Windows. To enable case sensitivity, you have to set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Kernel\obcaseinsensitive to 0 in the registry (and restart Windows).

Now, when I did this, flinux wouldn't start when ran from Total Commander, but ran fine from a cmd opened directly from windows. The cause is that GetCurrentDirectoryW doesn't always give the real actual name of the current directory (I guess it depends on how it was set).

For example, ran from Total commander, the path looks like d:\Prog\flinux-env, but when ran from a cmd opened directly from windows, it looks like D:\Prog\flinux-env. Notice the drive letter difference. The problem is, the drive's real name is 'D:' with a capital D, so now that file access is case sensitive, flinux can't open anything in the Total Commander case.

Idea for a fix:
In winfs, don't always just append the root path to the file being acted on. Rather, on initialization first find the real path of the root/current directory somehow (maybe by opening it by CreateFile, then using GetFinalPathNameByHandle) then opening it with NtCreateFile, and storing the handle. Then later on, when opening a file, set this handle in the ObjectAttributes RootDirectory parameter of NtCreateFile, and use a relative path.

@wishstudio
Copy link
Owner

I once tried to use relative paths but found an issue.

Say your RootDirectory points to D:\Prog\flinux-env and it's the root directory of flinux (i.e. "/" in flinux). If user tries to open the file /.., by linux path resolution semantics it should still open the root directory, but if you use relative path you will escape the root and instead open D:\Prog. I don't know any way to fix this problem.

@Sh4rK
Copy link
Contributor Author

Sh4rK commented Sep 4, 2015

We can preprocess all paths before doing the actual file operations (resolve .. and .) and going "above" root can be handled there. On another note, we should also be able to reuse most parts of winfs to mount out-of-root paths, to be able to access the rest of the windows filesystem.

@wishstudio
Copy link
Owner

No, preprocessing .. before file operations is actually wrong.

Take this example, let's say /bin is a symlink to /usr/bin. Then /bin/.. actually points to /usr instead of /. This is very confusing but unfortunate truth. In flinux, to mimic this behavior, we resort to resolve the components one by one.

Back to this issue, isn't there any reliable way to get case correct path of current directory? (maybe via GetFinalPathNameByHandle() or NtQueryInformationFile(FileNameInformation)) If this is possible we don't need to mess using directory handles and relative paths.

@Sh4rK
Copy link
Contributor Author

Sh4rK commented Sep 4, 2015

GetFinalPathNameByHandle seems to work.
Calling it like GetFinalPathNameByHandleA(file, buf, sizeof(buf), FILE_NAME_NORMALIZED); (using narrow char version just for simplicity's sake) I get \\?\D:\Prog\flinux-env in every case. Only thing to do is then change the second \ to ? and we're done.

On a related note, is the \??\ namespace documented somewhere? The closest I found was \\?\, but the two doesn't seem to be the same thing.

@Sh4rK
Copy link
Contributor Author

Sh4rK commented Sep 4, 2015

Oh and back to the relative directory problem, you said

In flinux, to mimic this behavior, we resort to resolve the components one by one.

I don't see why this wouldn't work with relative dir handles too.

@wishstudio
Copy link
Owner

Ok. Go ahead with the relative paths for handling current directory. We just need to find a reliable way to open the handle to current directory. I think something like CreateFile(".") should work.

Per my knowledge, \\?\ is used in Win32 functions to denote a long (>256) path name. \??\ is used when specifying path names for native functions. Because native functions normally does not accept Win32 paths, using that let the functions treat the path as a Win32 path, without the need to do the (complex) conversion manually.

@Sh4rK
Copy link
Contributor Author

Sh4rK commented Sep 4, 2015

In my test I just used GetCurrentDirectory then CreateFile on that path, But yes, using CreateFile(".", ...) does work. Actually, it doesn't even need to be ".", it could be read from the cmd line (to achieve what you've written in #59).

Regarding the relative path stuff, if you think it wouldn't make anything better or make things worse, I don't want to force anything, just having ideas.

@wishstudio
Copy link
Owner

I was thinking that if GetCurrentDirectory() fails, we can only go this way to support case sensitivity.

Just now I realized we can also apply GetFinalPathNameByHandle() afterwards and continue current approach of path concatenation.

Actually I cannot decide which approach is better at this point. To make a conclusion we need to also consider some unimplemented functions like chroot ( #59 ).

For now maybe using path concatenation is more reasonable since it requires very small modification to the code to fix this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants