wireshift-fallback 0.1.1

Blocking worker-pool fallback backend for wireshift
Documentation
use std::collections::HashMap;
use std::path::PathBuf;

use rustix::fs::{openat, Mode, OFlags, CWD};
use wireshift_core::op::CompletionPayload;
use wireshift_core::{Error, Result};

pub(crate) fn execute_openat(
    dir: Option<std::fs::File>,
    path: PathBuf,
    flags: u32,
    read: bool,
    write: bool,
    create: bool,
    truncate: bool,
) -> Result<CompletionPayload> {
    Ok(CompletionPayload::File(open_file_at(
        dir, path, flags, read, write, create, truncate,
    )?))
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn execute_openat_direct(
    dir: Option<std::fs::File>,
    path: PathBuf,
    flags: u32,
    read: bool,
    write: bool,
    create: bool,
    truncate: bool,
    slot: u32,
    fixed_files: &mut HashMap<u32, std::fs::File>,
) -> Result<CompletionPayload> {
    let file = open_file_at(dir, path, flags, read, write, create, truncate)?;
    if fixed_files.insert(slot, file).is_some() {
        return Err(Error::completion(
            format!("direct descriptor slot {slot} was reused before close"),
            "ensure each chained direct descriptor slot is closed exactly once",
        ));
    }
    Ok(CompletionPayload::Unit)
}

fn open_file_at(
    dir: Option<std::fs::File>,
    path: PathBuf,
    flags: u32,
    read: bool,
    write: bool,
    create: bool,
    truncate: bool,
) -> Result<std::fs::File> {
    if path.as_os_str().is_empty() {
        return Err(Error::validation(
            "openat path must not be empty",
            "provide a non-empty filesystem path",
        ));
    }
    if dir.is_some() && path.is_absolute() {
        return Err(Error::validation(
            "openat path must be relative when a directory handle is provided",
            "pass a relative path or omit the directory file descriptor",
        ));
    }
    let oflags = open_flags(flags, read, write, create, truncate)?;
    let create_mode = if create {
        Mode::from_raw_mode(0o600)
    } else {
        Mode::empty()
    };
    let file = if let Some(dir) = dir {
        std::fs::File::from(openat(&dir, &path, oflags, create_mode).map_err(|error| {
            Error::io(
                "openat failed",
                error.into(),
                "ensure the relative path exists under the provided directory and permissions are correct",
            )
        })?)
    } else {
        std::fs::File::from(openat(CWD, &path, oflags, create_mode).map_err(|error| {
            Error::io(
                "openat failed",
                error.into(),
                "ensure the path exists and permissions are correct",
            )
        })?)
    };
    apply_open_hints(&file, flags)?;
    Ok(file)
}

fn open_flags(
    open_flags: u32,
    read: bool,
    write: bool,
    create: bool,
    truncate: bool,
) -> Result<OFlags> {
    let mut flags = match (read, write) {
        (true, true) => OFlags::RDWR,
        (true, false) => OFlags::RDONLY,
        (false, true) => OFlags::WRONLY,
        (false, false) => {
            return Err(Error::validation(
                "openat must request read and/or write access",
                "enable read_only or create a read-write open request",
            ));
        }
    };
    if create {
        flags |= OFlags::CREATE;
    }
    if truncate {
        flags |= OFlags::TRUNC;
    }
    flags |= OFlags::from_bits_retain(open_flags & !sequential_hint_bit());
    flags |= OFlags::CLOEXEC;
    Ok(flags)
}

fn apply_open_hints(file: &std::fs::File, flags: u32) -> Result<()> {
    if flags & sequential_hint_bit() == 0 {
        return Ok(());
    }
    rustix::fs::fadvise(file, 0, None, rustix::fs::Advice::Sequential).map_err(|error| {
        Error::io(
            "posix_fadvise(SEQUENTIAL) failed after openat",
            std::io::Error::from(error),
            "remove OpenFlags::SEQUENTIAL or ensure the target filesystem supports fadvise",
        )
    })?;
    Ok(())
}

const fn sequential_hint_bit() -> u32 {
    1 << 31
}