Add std.os.getFdPath and std.fs.Dir.realpath#5701
Conversation
|
The Windows failure here looks legit |
Thanks for having a look! Windows still surprises me at times. Anyhow, I've fixed the tests. I was wondering though, should this be documented somewhere, or is this common knowledge (or at least expected) on Windows (that running |
|
@squeek502, since #5684 landed, I've gone ahead and fixed the TODO. :-) |
lib/std/fs.zig
Outdated
| /// relative to this `Dir`. If `pathname` is absolute, ignores this `Dir` handle | ||
| /// and returns the canonicalized absolute pathname of `pathname` argument. | ||
| /// Caller must free the returned memory. | ||
| pub fn realpath(self: Dir, allocator: *Allocator, pathname: []const u8) ![]u8 { |
There was a problem hiding this comment.
Following conventions, I think this should be realpathAlloc and there should be a realpath, realpathZ, and realpathW that take a slice as a buffer. See std.fs.realpath and friends:
Lines 26 to 29 in bb55889
There was a problem hiding this comment.
Excellent point, thanks! Will tweak and report back.
There was a problem hiding this comment.
@squeek502 I've now added first pass at implementing your suggestion. It'd be great if you could have a look and lemme know if there's any missing, or if something could be improved upon, etc.
There was a problem hiding this comment.
I didn't realize that the os.realpath functions use *[MAX_PATH_BYTES]u8 for their out_buffer params. Changing Dir.realpath and friends to use that instead of []u8 would allow for removing the intermediate buffers in their implementations which seems nicer to me. Definitely worth waiting for @andrewrk to chime in on that before changing it though.
There was a problem hiding this comment.
Oh, yeah, that’s correct. It’d be great to change the interface from array to slice in std.os.realpath and friends but my suggestion would be doing it in a subsequent PR. Would that make sense?
d331b01 to
36aaff7
Compare
andrewrk
left a comment
There was a problem hiding this comment.
Nice work @kubkon.
I want to be careful about how to do this. It looks like realpathat is not a widely portable abstraction that we can provide. Now, that does not mean that we cannot provide it, but it should be very clear, at least from the doc comments, that this is not universally supported API, and will cause compile errors on some operating systems.
Furthermore - this API should be avoided for the cache hash API, because for our purposes there, we do want a widely portable API that works on all OS's.
Does this make sense? I can take a look at the cache hash PR and provide some guidance there too, if that would help.
lib/std/os.zig
Outdated
| else => { | ||
| var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined; | ||
| const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable; | ||
|
|
||
| return readlinkZ(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer); | ||
| }, |
There was a problem hiding this comment.
This is Linux-specific logic so it should go into a .linux => prong. The one that goes into else should be one that looks like it would work for POSIX systems in general, which, in this case, would be the macos prong. However I looked into it a bit and it seems that other operating systems *do not support the concept of realpathat, which makes me want to be very careful about how the std lib goes about this.
There was a problem hiding this comment.
This should be a compile error on operating systems that don't support this API
There was a problem hiding this comment.
That's an excellent point, thanks for pointing it out @andrewrk. I'm not sure why I erroneously assumed that for instance, what is true for Linux is also true for BSDs (looking at you here, FreeBSD). All in all, I agree with you here 100%, and I'll make sure to have any other host return a compile error on an attempt at using realpathat. For more context and for anyone joining in in this discussion, FreeBSD is an example of an OS which generally doesn't (officially at least, and in a non-hacky way) support querying the OS for a canonical path of a file descriptor. One excellent source describing this, can be found here. BTW, I'll make sure to add this to the docs.
There was a problem hiding this comment.
@andrewrk OK, I've made sure we throw a compile error for all unsupported hosts. In other words, we currently support linux, macos and windows, and for all others, it's a compile error.
While we're here, do you think we should explicitly return a compile error in std.os.realpathat for unsupported hosts as well, or let it drop down to fdPath and the error bubble up from them?
There was a problem hiding this comment.
I've renamed fdPath to getFdPath and I've tweaked the docs to clearly state that both getFdPath and realpathat are not supported on all hosts.
Makes sense! So #5636 does provide a couple of bug fixes to |
hmm, if you don't mind, let's focus on this API layer first, and make sure we feel good about it, then move on to cache hash |
@andrewrk Right, that's what I meant, sorry. Lemme clarify a bit more. So when working on cache hash, I've also added a couple of niceties to |
Yeah that sounds good 👍 |
Cool, I'll get on it then! Thanks for your patience, and sorry about the confusion! :-) |
|
@andrewrk commits migrated! So now, |
|
The reason for timeout on Linux was a bug in |
f0a7510 to
fbbd01a
Compare
|
I've decided to redo this PR in a major way such that:
@andrewrk would you care to take another look at this PR? |
`std.os.getFdPath` is very platform-specific and can be used to query the OS for a canonical path to a file handle. Currently supported hosts are Linux, macOS and Windows. `std.fs.Dir.realpath` (and null-terminated, plus WTF16 versions) are similar to `std.os.realpath`, however, they resolve a path wrt to this `Dir` instance. If the input pathname argument turns out to be an absolute path, this function reverts to calling `realpath` on that pathname completely ignoring this `Dir`.
std.os.realpathatis similar tostd.os.realpath, however, it acceptsa pairfd_t, []const u8of args and thus works out the realpathof a relative path wrt to some opened file descriptor.If the input pathname argument turns out to be an absolute path, thisfunction reverts to callingrealpathon that pathname completelyignoring the input file descriptor. This behaviour is standard inPOSIX and IMHO a good rule of thumb to follow.If the input file descriptor was obtained usingstd.fs.cwd()call,this function reverts tostd.os.getcwd()to obtain the filedescriptor's path.std.fs.Dir.realpathintegratesstd.os.realpathatwithstd.fs.Dirbut with dynamic memory allocator.Part 1 of #5636.EDIT:
See the comments for an update of the contents of this PR.