Skip to content
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

API for deleted files / raw FD #317

Open
tatref opened this issue Oct 16, 2024 · 0 comments
Open

API for deleted files / raw FD #317

tatref opened this issue Oct 16, 2024 · 0 comments

Comments

@tatref
Copy link
Contributor

tatref commented Oct 16, 2024

Hi,

If a file is deleted while still opened by a process, the fd under /proc/$pid/fd/$fd will show up as

[tatref@srv dev]$ ls -ld /proc/12779/fd/*
lr-x------ 1 tatref tatref 64 Oct 16 01:00 /proc/12779/fd/4 -> '/home/tatref/dev/tes (deleted)'

We can get that info with

use std::fs::File;
use std::fs::Metadata;
use std::os::unix::fs::MetadataExt;

let f = File::open(&format!("/proc/{}/fd/{}", p.pid, fd.fd)).unwrap();
let metadata = f.metadata().unwrap();

if metadata.nlink() == 0 {}

So this means format a String, open a file, and do a syscall to get metadata.

Currently it seems there is no easier API in procfs to access this information (please correct me if I'm wrong).
FDTarget has a Path variant, but there is no guarantee that another file with the same name hasn't be created.

Maybe we could store a File in the FDInfo, and add it where it is created:

fn from_process_at<P: AsRef<Path>, Q: AsRef<Path>>(
base: P,
dirfd: BorrowedFd,
path: Q,
fd: i32,
) -> ProcResult<Self> {
let p = path.as_ref();
let root = base.as_ref().join(p);
// for 2.6.39 <= kernel < 3.6 fstat doesn't support O_PATH see https://github.com/eminence/procfs/issues/265
let flags = match Version::cached() {
Ok(v) if v < KernelVersion::new(3, 6, 0) => OFlags::NOFOLLOW | OFlags::CLOEXEC,
Ok(_) => OFlags::NOFOLLOW | OFlags::PATH | OFlags::CLOEXEC,
Err(_) => OFlags::NOFOLLOW | OFlags::PATH | OFlags::CLOEXEC,
};
let file = wrap_io_error!(root, rustix::fs::openat(dirfd, p, flags, Mode::empty()))?;
let link = rustix::fs::readlinkat(&file, "", Vec::new()).map_err(io::Error::from)?;
let md =
rustix::fs::statat(&file, "", AtFlags::SYMLINK_NOFOLLOW | AtFlags::EMPTY_PATH).map_err(io::Error::from)?;
let link_os = link.to_string_lossy();
let target = FDTarget::from_str(link_os.as_ref())?;
Ok(FDInfo {
fd,
mode: (md.st_mode & Mode::RWXU.bits()) as u16,
target,
})
}

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant