Change:
Files On Demand is a new OneDrive feature that only downloads files to the local disk when needed. Install the latest Windows and OneDrive updates Open OneDrive settings, enable Files On Demand Run this code with the path to your OneDrive folder: Output: Here's a PR in libuv that fixed an issue with Files On Demand, in case there's a similar issue in Rust: Ref: and Microsoft/vscode
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 supposed to return information on the target of the reparse point, not the reparse point itself. To quote the documentation "This function will traverse symbolic links to query information about the destination file." Therefore the fact that this doesn't follow the reparse point and simply says that it is a reparse point is a bug.
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.
You could poke around with calling directly on that directory and figure out how to determine that it is indeed a directory.
Don't know if this helps: The file attributes for a file and a directory in onedrive - both have . The file has (?). The directory has which seems to make sense.
The implementation of actually has a lot of problems. Compare to . Let's ignore the fact that there are a lot more factors on the Windows side for now. The particular issue in this thread is caused by line 523, where to be considered a directory, we expect the reparse point flag to be false and the dir flag to be true. That's, um, bad. But pretty much every function in that impl is wrong - it should work the same way the Unix version does, where it stores the native mode and each checks for the existence of the appropriate flag. Maybe someone more familiar with Unix can say whether a symlink to a file should be treated as or just ? Now, is a little harder to solve. Actually, if you say that mount points are symlinks which this does, you're kind of in messy territory here because reparse points are totally up to the FS driver. So one way or another, symlink detection is broken here because you are basically saying a symlink is a reparse point that resolves to another FS location, but you can't make that judgment just from the flags. All those tell you is that it's a particular thing that Microsoft implemented, but there's no reason you can't have other implementations that act like symlinks. To actually figure this stuff out correctly you need to do what libuv is doing and try to get the FS driver to treat the reparse point as what you're looking for. 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 mode - you should check for the existence of a symlink flag and a dir flag, but I'd make a doc comment above that function noting that it's broken and actually only tells you if the thing is a Win32 symlink or a mount point. How it should work may need some discussion, I'm not sure.
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.
Do you happen to have any context on what led to with respect to this bug?
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 file types on Windows behave pretty different from Unix. I would not call the logic 'wrong' as does, but more a best effort to a cross-platform interface. I think the easiest solution is to change  to something like (not tested): 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.
For the record, is an old meant for backup tools. 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")

Discussion:
fn file_size(&self) -> u64 { self.as_inner().size() } } <ins> /// Add support for the Windows specific fact that a symbolic link knows whether it is a file /// or directory. #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. #[unstable(feature = "windows_file_type_ext", issue = "0")] fn is_symlink_dir(&self) -> bool; /// Returns whether this file type is a symbolic link that is also a file. #[unstable(feature = "windows_file_type_ext", issue = "0")] fn is_symlink_file(&self) -> bool; } #[unstable(feature = "windows_file_type_ext", issue = "0")] impl FileTypeExt for fs::FileType { fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() } fn is_symlink_file(&self) -> bool { self.as_inner().is_symlink_file() } } </ins> /// Creates a new file symbolic link on the filesystem. /// /// The `dst` path will be a file symbolic link pointing to the `src`

} #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] <del> pub enum FileType { Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint, </del> <ins> pub struct FileType { attributes: c::DWORD, reparse_tag: c::DWORD, </ins> } pub struct ReadDir {

impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { <del> match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0, attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0, reparse_tag) { (false, false, _) => FileType::File, (true, false, _) => FileType::Dir, (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile, (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir, (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint, (_, true, _) => FileType::ReparsePoint, // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint // to indicate it is something symlink-like, but not something you can follow. </del> <ins> FileType { attributes: attrs, reparse_tag: reparse_tag, </ins> } } <del> pub fn is_dir(&self) -> bool { *self == FileType::Dir } pub fn is_file(&self) -> bool { *self == FileType::File } </del> <ins> pub fn is_dir(&self) -> bool { !self.is_symlink() && self.is_directory() } pub fn is_file(&self) -> bool { !self.is_symlink() && !self.is_directory() } </ins> pub fn is_symlink(&self) -> bool { <del> *self == FileType::SymlinkFile || *self == FileType::SymlinkDir || *self == FileType::MountPoint </del> <ins> self.is_reparse_point() && self.is_reparse_tag_name_surrogate() </ins> } pub fn is_symlink_dir(&self) -> bool { <del> *self == FileType::SymlinkDir || *self == FileType::MountPoint </del> <ins> self.is_symlink() && self.is_directory() } pub fn is_symlink_file(&self) -> bool { self.is_symlink() && !self.is_directory() } fn is_directory(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } fn is_reparse_tag_name_surrogate(&self) -> bool { self.reparse_tag & 0x20000000 != 0 </ins> } }