-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Add std.os.getFdPath and std.fs.Dir.realpath #5701
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
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
pub const realpath = os.realpath; | |
pub const realpathZ = os.realpathZ; | |
pub const realpathC = @compileError("deprecated: renamed to realpathZ"); | |
pub const realpathW = os.realpathW; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent point, thanks! Will tweak and report back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a compile error on operating systems that don't support this API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 👍
std.os.realpathat
is similar tostd.os.realpath
, however, it acceptsa pairfd_t, []const u8
of 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 callingrealpath
on 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.realpath
integratesstd.os.realpathat
withstd.fs.Dir
but with dynamic memory allocator.Part 1 of #5636.EDIT:
See the comments for an update of the contents of this PR.