Get metadata from file descriptor

I need to get the device ID and Inode number from a file descriptor, i.e. st_dev and st_ino. Conveniently, MetadataExt from std::os::linux::fs exposes these on the standard std::fs::Metadata struct.

However, I don't find a way to get a Metadata struct from any kind of FD (RawFd, BorrowedFd, etc.) in standard Rust. Essentially, I'd like to do a fstat, but this doesn't seem to be exposed in Rust.

Currently I'm using the following unsafe code:

/// Get metadata from a file descriptor.
fn metadata_from_fd(fd: BorrowedFd) -> std::io::Result<Metadata> {
    // SAFETY: We consume the FD here, but we move it back out later on to not consume it
    unsafe {
        let f = File::from_raw_fd(fd.as_raw_fd());
        let result = f.metadata();
        // Move the file descriptor back out of File to avoid closing it.
        let _ = OwnedFd::from(f);
        result
    }
}

Is this really the way to go in standard Rust?

I'm aware that nix or rustix probably support this, but in my codebase this is literally the only place where I'd need this, and I'd like to avoid a comparatively heavy dependency like nix for a single call side.

The io safety stuff just landed in 1.63, but I think you want

/// Get metadata from a file descriptor.
fn metadata_from_fd(fd: BorrowedFd<'_>) -> std::io::Result<Metadata> {
    let owned = fd.try_clone_to_owned()?;
    let f = File::from(owned);
    f.metadata()
}

Playground.

I've seen try_clone_to_owned, but as far as I can see it makes another syscall to duplicate the file descriptor, which I'd like to avoid, because it seems redundant to me just a single subsequent fstat call :person_shrugging:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.