-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
std.fs.IterableDir.Walker
doesn't ignore macOS "firmlinks" as it does symlinks, resulting in iterating some dirs twice and sometimes infinite loops
#13355
Comments
A more-or-less equivalent Rust program shares the behaviour of Zig, but Swift does not. This makes me think the dir walker code in each language's libraries does in fact need to handle firmlinks specifically and that Swift must do do. This despite claims they should be transparent to existing code. Here's my Swift code's output:
And the Swift code itself. You can see there's no special code for firmlinks: import Foundation
import AppKit
let fileManager = FileManager.default
let resKeys : [URLResourceKey] = [.isDirectoryKey, .fileSizeKey, .isSymbolicLinkKey]
let startURL: URL = URL(string: fileManager.currentDirectoryPath)!
guard CommandLine.arguments.count == 3 else {
print("** usage: dirwalker path string")
exit(1);
}
let pathArg = CommandLine.arguments[1]
let matchArg = CommandLine.arguments[2]
if let path = pathArg.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
if let url = URL(string: path) {
let en = fileManager.enumerator(at: url,
includingPropertiesForKeys: resKeys,
options: [.producesRelativePathURLs],
errorHandler: { (url, error) -> Bool in
return true }
)!
mainloop: for case let fileURL as URL in en {
do {
let rv = try fileURL.resourceValues(forKeys: Set(resKeys))
if let d = rv.isDirectory, d {
let filename: String = fileURL.lastPathComponent;
if filename.contains(matchArg) {
print(fileURL.relativePath)
}
}
} catch {
print("** error 2:", error)
}
}
}
}
print("done") |
I did research this issue a while back, but here are my findings/notes in case it might help someone who wants to implement it or comment their opinion on it:
What's interesting is that MacOS's Here are way that I think can be used to solve this is:
I am not sure what's the best approach here as there aren't many system firmlinks and it's uncommon to synthesize (if that's even possible). Note: I could be missing some other info, but this is what I have found. |
std.fs.IterableDir.Walker
doesn't ignore macOS "firmlinks" as it does symlinks, resulting in iterating over some dirs twicestd.fs.IterableDir.Walker
doesn't ignore macOS "firmlinks" as it does symlinks, resulting in iterating some dirs twice and sometimes infinite loops
Zig Version
0.10.0-dev.4324+c23b3e6fd
Steps to Reproduce and Observed Behavior
This is probably not a fully minimal example but I'm not fluent in Zig yet:
Run it with a starting path and a substring to search for. It will walk the directory and print out all paths that contain the substring after a
>
symbol and then its resolved canonical path after a»
symbol on the next line.I can only see the wrong behaviour when running in the root directory
/
as macOS has several directories from/System/Volumes/Data/x
linked to/x
using "firmlinks", which is a feature of the APFS filesystem going back to Sierra. Example firmlinked directories./Library
->/System/Volumes/Data/Library
/Users
->/System/Volumes/Data/Users
/Applications
->/System/Volumes/Data/Applications
I can't find Apple official documentation on firmlinks. Apparently they're supposed to be transparent and not affect most code. I also don't know how to get them to show up using
ls
. Thels
commandline I know that will show the most extra info macOS-specific info isls -alO@ /
but that doesn't seem to reveal them unlesssunlnk
means this and only this:Sample commandline:
Actual output:
Expected Behavior
Directories should only be listed at their true locations as is the case with symlinks, not also at the locations they're firmlinked to. I believe that would look like this:
The text was updated successfully, but these errors were encountered: