Skip to main content

dope_sys/io/file/
raw.rs

1use std::{mem::MaybeUninit, os::fd};
2
3use crate::{
4    Errno,
5    io::file::{self, Opened},
6    kernel,
7};
8
9pub(super) fn read_at<'a, S: kernel::raw::Source + ?Sized, E: From<Errno>>(
10    file: fd::BorrowedFd<'_>,
11    output: &'a mut [MaybeUninit<u8>],
12    offset: file::Offset,
13) -> Result<&'a mut [u8], E> {
14    use fd::AsRawFd as _;
15
16    const { assert!(libc::off_t::MAX as u64 == i64::MAX as u64) };
17    // SAFETY: the descriptor stays borrowed, output owns its writable extent,
18    // and the admitted nonnegative offset fits the ABI.
19    let raw = unsafe {
20        libc::pread(
21            file.as_raw_fd(),
22            output.as_mut_ptr().cast(),
23            output.len(),
24            offset.get() as libc::off_t,
25        )
26    };
27    // SAFETY: pread returns -1 or initializes at most this exact extent.
28    Ok(unsafe {
29        crate::io::raw::Buffer::try_native(output, raw, || kernel::raw::Code::last::<S>().into())?
30            .assume_init_mut()
31    })
32}
33
34/// # Safety
35/// The live descriptor remains unchanged until stream drop.
36/// Returned names retain exclusive storage until their borrows end.
37pub unsafe trait Directory: kernel::raw::Source {
38    type Stream;
39
40    fn open_dir<E: From<Errno>>(path: &std::ffi::CStr) -> Result<Self::Stream, file::OpenError<E>>
41    where
42        Self: file::File,
43    {
44        let file = Self::open(
45            path,
46            file::Open::DIRECTORY | file::Open::CLOSE_ON_EXEC,
47            file::Mode::new(0),
48        )
49        .map_err(file::OpenError::Syscall)?;
50        Self::from_fd(file)
51    }
52
53    fn from_fd<E: From<Errno>>(file: fd::OwnedFd) -> Result<Self::Stream, file::OpenError<E>>;
54    fn descriptor(stream: &Self::Stream) -> kernel::raw::Descriptor;
55    fn next<E: From<Errno>>(
56        stream: &mut Self::Stream,
57    ) -> Result<Option<file::Entry<'_>>, file::ReadError<E>>;
58}
59
60/// # Safety
61/// Each decoded success retains the uniquely transferred descriptor until
62/// delivery or reclamation. Closing consumes that ownership.
63pub unsafe trait Completion {
64    type Outcome;
65    type Invalid;
66
67    /// # Safety
68    /// A successful outcome transfers one live descriptor from a completed
69    /// open operation. Its descriptor has not been decoded or reclaimed before.
70    unsafe fn open(outcome: Self::Outcome) -> Result<Opened, Self::Invalid>;
71
72    fn close(file: fd::OwnedFd) -> Result<(), Errno>;
73}