Similar to File::metadata(). File::metadata(), to my understanding, maps to fstat and GetFileInformationByHandle, which could also be called with the file descriptor / handle of stdout.
The use-case for this is that in uutils (a rust coreutils rewrite, specifically the cat utility) we need to check if stdout is the same as an input file and adjust our behavior accordingly.
Yes. I should have clarified that it's not impossible to do in rust now, and I know how to work around it. i.e. The code I've written would be more idiomatic and cleaner if I hadn't had to write platform-dependent code and add a dependency per platform.
If the stdin handle is a filesystem file then yes you can. If it's a device then some metadata can be queried (e.g. type, path) but GetFileInformationByHandle itself may fail.
Without the dependency, you do need to write platform specific code. One possible way to avoid that might be if stdin/stdout/stderr had methods that turned them into a File. That would give you the most flexibility. However, this approach doesn't work on its own, since once the File is dropped, the device will be closed. There are likely other issues. So a metadata method of some sort might be a decent compromise.
Ah, I obviously should have searched crates.io before writing it myself. However, at first glance same-file doesn't allow to compare two symlinks (i.e. compare metadata obtained from lstat (unix) or a file handle opened with FILE_FLAG_OPEN_REPARSE_POINT set (windows)). It probably doesn't matter, but the use case here is cp, which does not allow the destination to be a symlink it just created.
It's a bit unorthodox, but I think returning a &'static File would work. That'd still let you do odd things, but at least it wouldn't be easy to misuse accidentally.
You could still get an owned File from it by using File::try_clone (approximately dup(2) under the hood), so it would also become possible to do reads and writes, bypassing the usual locks. But the existence of that method shows that that sort of funny business is possible already, if only for Files, so I'm not sure that's a dealbreaker.
Doing this means that stdin (and likely the other std* streams) cannot be closed (and likely dup2'd over). I don't think Rust's stdlib API could expose this without closing off those (valid) use cases.
If you have a File to a closed file descriptor, any open call can result in the same file descriptor. This violates IO safety. 3128-io-safety - The Rust RFC Book
I'm still not sure if it applies here. If you close/replace stdin it already affects Stdin, which effectively owns libc::STDIN_FILENO, so wouldn't that already violate I/O safety? Would providing a &'static File make that any worse?
Closing stdin, stdout or stderr on Unix makes many programs misbehave. On Windows, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE can't be accidentally overwritten by an open I believe. If you replace stdin it is your own responsibility to provide an fd that doesn't make the program misbehave when it tries to read/write to it. A File allows much more operations than Stdin/Stdout/Stderr and libraries may assume that a File is backed by an actual file, while they don't expect Stdin/Stdout/Stderr to always be backed by a pipe.
Closing (or, rather, dup2'ing over them) stdin and friends isn't that uncommon after a fork. It's bog standard behavior for a shell at least. However, this may be covered by the POSIX rules for what kinds of things may occur between fork and exec (especially in the presence of threads).