-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Path.is_dir returns false for folders in OneDrive using "Files On Demand" #46484
Comments
Are you sure this is a bug? Seems like those folders are indeed reparse points and only look like folders to the user. |
I guess I'm not sure what the expected result is. Node says it's a directory:
|
When given a reparse point |
Is there anything I can help with on this bug? It's the root cause of a nasty bug that prevents vscode from searching inside some OneDrive folders. I could attempt a PR, if someone can give me some pointers. |
@roblourens You could poke around with calling |
Don't know if this helps: let metadata = Path::new(onedrive_file).metadata().expect("failed");
println!("{:?}", metadata.file_attributes()); // 1056
let metadata2 = Path::new(onedrive_dir).metadata().expect("failed");
println!("{:?}", metadata2.file_attributes()); // 1040 The file attributes for a file and a directory in onedrive - both have https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx |
The implementation of Now, For the purpose of getting ripgrep to work, I would just refactor the methods to check for native flags like I described in the first paragraph. There should not be a |
Thanks for the notes. I may try to work around this downstream just for fixing search in VS Code, but I think that coming up with the right fix for Rust is outside my area of expertise. But I'm hoping that someone is able to look at this because I think it's quite a bad bug. |
@pitdicker Do you happen to have any context on what led to this change with respect to this bug? |
This commit fixes a bug on Windows where walkdir refused to traverse directories that resided on OneDrive via its "file on demand" strategy. The specific bug is that Rust's standard library treats a reparse point (which is what OneDrive uses) as distinct from a file or directory, which wreaks havoc on any code that uses FileType::{is_file, is_dir}. We fix this by checking the directory status of a file by looking only at whether its directory bit is set. This bug was originally reported in ripgrep: BurntSushi/ripgrep#705 It has also been filed upstream: rust-lang/rust#46484 And has a pending fix: rust-lang/rust#47956
This commit fixes a bug on Windows where directory traversals were completely broken when attempting to scan OneDrive directories that use the "file on demand" strategy. The specific problem was that Rust's standard library treats OneDrive directories as reparse points instead of directories, which causes methods like `FileType::is_file` and `FileType::is_dir` to always return false, even when retrieved via methods like `metadata` that purport to follow symbolic links. We fix this by peppering our code with checks on the underlying file attributes exposed by Windows. We consider an entry a directory if and only if the directory bit is set on the attributes. We are careful to make sure that the code remains the same on non-Windows platforms. Note that we also bump the dependency on `walkdir`, which contains a similar fix for its traversals. This bug is recorded upstream: rust-lang/rust#46484 Upstream also has a pending PR: rust-lang/rust#47956 Fixes #705
I sort-of remember writing that code, but forgot the details. It was an effort to get symlinks on Windows in a mostly working state. Would have to dive into the details again to be of much use to be honest. As @retep998 commented file types on Windows behave pretty different from Unix. I would not call the logic 'wrong' as @parkovski does, but more a best effort to a cross-platform interface. I think the easiest solution is to change
So just act as if it really is a file or directory if we don't recognize the reparse point as a symlink or directory junction. |
This is the ideal FileType on Windows. You may not like it, but this is what peak performance looks like. Theoretically this would fix #46484 The current iteration of this PR should not cause existing code to break, but instead merely improves handling around reparse points. Specifically... * Reparse points are considered to be symbolic links if they have the name surrogate bit set. Name surrogates are reparse points that effectively act like symbolic links, redirecting you to a different directory/file. By checking for this bit instead of specific tags, we become much more general in our handling of reparse points, including those added by third parties. * If something is a reparse point but does not have the name surrogate bit set, then we ignore the fact that it is a reparse point because it is actually a file or directory directly there, despite having additional handling by drivers due to the reparse point. * For everything which is not a symbolic link (including non-surrogate reparse points) we report whether it is a directory or a file based on the presence of the directory attribute bit. * Notably this still preserves invariant that when `is_symlink` returns `true`, both `is_dir` and `is_file` will return `false`. The potential for breakage was far too high. * Adds an unstable `FileTypeExt` to allow users to determine whether a symbolic link is a directory or a file, since `FileType` by design is incapable of reporting this information.
@roblourens For the record, The FAT driver sets the Archive flag whenever you modify a file and a DOS-era backup tool operating in incremental backup mode can then go through, save copies of any files marked "Archive", and then clear the bit to indicate to its future self that they haven't changed since the previous incremental backup. (In other words, the "archive" part is short for "archival needed" or "please archive") |
This commit undoes a work-around for a bug in Rust's standard library that prevented correct file type detection on Windows in OneDrive directories. We remove the work-around because we are moving to a latest-stable Rust version policy, which has included this fix for a while now. ref #705, rust-lang/rust#46484
This commit undoes a work-around for a bug in Rust's standard library that prevented correct file type detection on Windows in OneDrive directories. We remove the work-around because we are moving to a latest-stable Rust version policy, which has included this fix for a while now. ref #705, rust-lang/rust#46484
Files On Demand is a new OneDrive feature that only downloads files to the local disk when needed.
Output:
Here's a PR in libuv that fixed an issue with Files On Demand, in case there's a similar issue in Rust: https://github.com/libuv/libuv/pull/1522/files
Ref: BurntSushi/ripgrep#705 and microsoft/vscode#35433
The text was updated successfully, but these errors were encountered: