Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the filename of an open std::fs::File in Rust?

Tags:

file

linux

rust

I have an open std::fs::File, and I want to get it's filename, e.g. as a PathBuf. How do I do that?

The simple solution would be to just save the path used in the call to File::open. Unfortunately, this does not work for me. I am trying to write a program that reads log files, and the program that writes the logs keep changing the filenames as part of it's log rotation. So the file may very well have been renamed since it was opened. This is on Linux, so renaming open files is possible.

How do I get around this issue, and get the current filename of an open file?

like image 454
Anders Avatar asked Jul 10 '20 19:07

Anders


People also ask

What does FS mean in Rust?

Filesystem manipulation operations. This module contains basic methods to manipulate the contents of the local filesystem.


2 Answers

On a typical Unix filesystem, a file may have multiple filenames at once, or even none at all. The file metadata is stored in an inode, which has a unique inode number, and this inode number can be linked from any number of directory entries. However, there are no reverse links from the inode back to the directory entries.

Given an open File object in Rust, you can get the inode number using the ino() method. If you know the directory the log file is in, you can use std::fs::read_dir() to iterate over all entries in that directory, and each entry will also have an ino() method, so you can find the one(s) matching your open file object. Of course this approach is subject to race conditions – the directory entry may already be gone again once you try to do anything with it.

like image 128
Sven Marnach Avatar answered Nov 14 '22 23:11

Sven Marnach


On linux, files handles held by the current process can be found under /proc/self/fd. These look and act like symlinks to the original files (though I think they may technically be something else - perhaps someone who knows more can chip in).

You can therefore recover the (possibly changed) file name by constructing the correct path in /proc/self/fd using your file descriptor, and then following the symlink back to the filesystem.

This snippet shows the steps:

use std::fs::read_link;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

// if f is your std::fs::File

// first construct the path to the symlink under /proc
let path_in_proc = PathBuf::from(format!("/proc/self/fd/{}", f.as_raw_fd()));

// ...and follow it back to the original file
let new_file_name = read_link(path_in_proc).unwrap();
like image 20
myrtlecat Avatar answered Nov 14 '22 22:11

myrtlecat