Как мне получить имя файла открытого std :: fs :: File в Rust? - PullRequest
3 голосов
/ 10 июля 2020

У меня есть открытый std::fs::File, и я хочу получить его имя файла, например, как PathBuf. Как мне это сделать?

Простым решением было бы просто сохранить путь, используемый при вызове, в File::open. К сожалению, у меня это не работает. Я пытаюсь написать программу, которая читает файлы журналов, и программа, которая записывает журналы, продолжает изменять имена файлов в рамках ротации журналов. Так что файл вполне мог быть переименован с момента открытия. Это Linux, поэтому возможно переименование открытых файлов.

Как мне обойти эту проблему и получить текущее имя файла открытого файла?

Ответы [ 2 ]

6 голосов
/ 10 июля 2020

В типичной файловой системе Unix файл может иметь несколько имен файлов одновременно или даже не иметь ни одного. Метаданные файла хранятся в inode , который имеет уникальный номер inode , и этот номер inode может быть связан с любым количеством записей каталога. Однако обратных ссылок от inode к записям каталога нет.

Учитывая открытый объект File в Rust, вы можете получить номер inode, используя метод ino() . Если вы знаете каталог, в котором находится файл журнала, вы можете использовать std::fs::read_dir() для перебора всех записей в этом каталоге, и каждая запись также будет иметь ino() метод , так что вы можете найти тот (ы), который соответствует вашему открытому файловому объекту. Конечно, этот подход зависит от условий гонки - запись в каталоге может уже исчезнуть, как только вы попытаетесь что-либо с ней сделать.

4 голосов
/ 10 июля 2020

В linux дескрипторы файлов, хранящиеся в текущем процессе, можно найти в /proc/self/fd. Они выглядят и действуют как символические ссылки на исходные файлы (хотя я думаю, что технически они могут быть чем-то другим - возможно, кто-то, кто знает больше, может вмешаться).

Таким образом, вы можете восстановить (возможно измененное) имя файла, построив правильный путь в /proc/self/fd с использованием вашего файлового дескриптора, а затем следуя символической ссылке обратно в файловую систему.

В этом фрагменте показаны шаги:

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();
...