Skip to content

Commit

Permalink
Support type-safe path FDs
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX committed Dec 8, 2022
1 parent 782a424 commit 4ca7899
Show file tree
Hide file tree
Showing 17 changed files with 193 additions and 168 deletions.
7 changes: 3 additions & 4 deletions src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
use crate::errno::Errno;
use crate::fcntl::{self, OFlag};
use crate::sys;
use crate::{sys, AsPathFd};
use crate::{Error, NixPath, Result};
use cfg_if::cfg_if;
use std::ffi;
use std::os::unix::io::AsFd;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::ptr;

Expand Down Expand Up @@ -44,8 +43,8 @@ impl Dir {
}

/// Opens the given path as with `fcntl::openat`.
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
dirfd: &Fd,
pub fn openat<Fd: AsPathFd, P: ?Sized + NixPath>(
dirfd: Fd,
path: &P,
oflag: OFlag,
mode: sys::stat::Mode,
Expand Down
56 changes: 29 additions & 27 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use std::os::unix::io::FromRawFd;
use std::os::unix::io::OwnedFd;
use std::os::unix::io::RawFd;

#[cfg(not(target_os = "redox"))]
use crate::AsPathFd;
#[cfg(feature = "fs")]
use crate::{sys::stat::Mode, NixPath, Result};
#[cfg(any(target_os = "android", target_os = "linux"))]
Expand Down Expand Up @@ -211,15 +213,15 @@ pub fn open<P: ?Sized + NixPath>(
// The conversion is not identical on all operating systems.
#[allow(clippy::useless_conversion)]
#[cfg(not(target_os = "redox"))]
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
dirfd: &Fd,
pub fn openat<Fd: AsPathFd, P: ?Sized + NixPath>(
dirfd: Fd,
path: &P,
oflag: OFlag,
mode: Mode,
) -> Result<OwnedFd> {
let fd = path.with_nix_path(|cstr| unsafe {
libc::openat(
dirfd.as_fd().as_raw_fd(),
dirfd.as_path_fd(),
cstr.as_ptr(),
oflag.bits(),
mode.bits() as c_uint,
Expand All @@ -230,18 +232,18 @@ pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
}

#[cfg(not(target_os = "redox"))]
pub fn renameat<Fd1: AsFd, P1: ?Sized + NixPath, Fd2: AsFd, P2: ?Sized + NixPath>(
old_dirfd: &Fd1,
pub fn renameat<Fd1: AsPathFd, P1: ?Sized + NixPath, Fd2: AsPathFd, P2: ?Sized + NixPath>(
old_dirfd: Fd1,
old_path: &P1,
new_dirfd: &Fd2,
new_dirfd: Fd2,
new_path: &P2,
) -> Result<()> {
let res = old_path.with_nix_path(|old_cstr| {
new_path.with_nix_path(|new_cstr| unsafe {
libc::renameat(
old_dirfd.as_fd().as_raw_fd(),
old_dirfd.as_path_fd(),
old_cstr.as_ptr(),
new_dirfd.as_fd().as_raw_fd(),
new_dirfd.as_path_fd(),
new_cstr.as_ptr(),
)
})
Expand All @@ -264,19 +266,19 @@ libc_bitflags! {
feature! {
#![feature = "fs"]
#[cfg(all(target_os = "linux", target_env = "gnu"))]
pub fn renameat2<Fd1: AsFd, P1: ?Sized + NixPath, Fd2: AsFd, P2: ?Sized + NixPath>(
old_dirfd: &Fd1,
pub fn renameat2<Fd1: AsPathFd, P1: ?Sized + NixPath, Fd2: AsPathFd, P2: ?Sized + NixPath>(
old_dirfd: Fd1,
old_path: &P1,
new_dirfd: &Fd2,
new_dirfd: Fd2,
new_path: &P2,
flags: RenameFlags,
) -> Result<()> {
let res = old_path.with_nix_path(|old_cstr| {
new_path.with_nix_path(|new_cstr| unsafe {
libc::renameat2(
old_dirfd.as_fd().as_raw_fd(),
old_dirfd.as_path_fd(),
old_cstr.as_ptr(),
new_dirfd.as_fd().as_raw_fd(),
new_dirfd.as_path_fd(),
new_cstr.as_ptr(),
flags.bits(),
)
Expand Down Expand Up @@ -404,10 +406,10 @@ pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {

#[cfg(not(target_os = "redox"))]
pub fn readlinkat<Fd: AsFd, P: ?Sized + NixPath>(
dirfd: &Fd,
dirfd: Fd,
path: &P,
) -> Result<OsString> {
inner_readlink(Some(dirfd), path)
inner_readlink(Some(&dirfd), path)
}
}

Expand Down Expand Up @@ -599,9 +601,9 @@ feature! {
/// returned.
#[cfg(any(target_os = "android", target_os = "linux"))]
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
fd_in: &Fd1,
fd_in: Fd1,
off_in: Option<&mut libc::loff_t>,
fd_out: &Fd2,
fd_out: Fd2,
off_out: Option<&mut libc::loff_t>,
len: usize,
) -> Result<usize> {
Expand All @@ -628,9 +630,9 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice<Fd1: AsFd, Fd2: AsFd>(
fd_in: &Fd1,
fd_in: Fd1,
off_in: Option<&mut libc::loff_t>,
fd_out: &Fd2,
fd_out: Fd2,
off_out: Option<&mut libc::loff_t>,
len: usize,
flags: SpliceFFlags,
Expand All @@ -657,8 +659,8 @@ pub fn splice<Fd1: AsFd, Fd2: AsFd>(

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn tee<Fd1: AsFd, Fd2: AsFd>(
fd_in: &Fd1,
fd_out: &Fd2,
fd_in: Fd1,
fd_out: Fd2,
len: usize,
flags: SpliceFFlags,
) -> Result<usize> {
Expand All @@ -675,7 +677,7 @@ pub fn tee<Fd1: AsFd, Fd2: AsFd>(

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn vmsplice<Fd: AsFd>(
fd: &Fd,
fd: Fd,
iov: &[std::io::IoSlice<'_>],
flags: SpliceFFlags,
) -> Result<usize> {
Expand Down Expand Up @@ -734,7 +736,7 @@ feature! {
#[cfg(any(target_os = "linux"))]
#[cfg(feature = "fs")]
pub fn fallocate<Fd: AsFd>(
fd: &Fd,
fd: Fd,
mode: FallocateFlags,
offset: libc::off_t,
len: libc::off_t,
Expand Down Expand Up @@ -810,7 +812,7 @@ impl SpacectlRange {
/// ```
#[cfg(target_os = "freebsd")]
pub fn fspacectl<Fd: AsFd>(
fd: &Fd,
fd: Fd,
range: SpacectlRange,
) -> Result<SpacectlRange> {
let mut rqsr = libc::spacectl_range {
Expand Down Expand Up @@ -861,7 +863,7 @@ pub fn fspacectl<Fd: AsFd>(
/// ```
#[cfg(target_os = "freebsd")]
pub fn fspacectl_all<Fd: AsFd>(
fd: &Fd,
fd: Fd,
offset: libc::off_t,
len: libc::off_t,
) -> Result<()> {
Expand Down Expand Up @@ -917,7 +919,7 @@ mod posix_fadvise {
feature! {
#![feature = "fs"]
pub fn posix_fadvise<Fd: AsFd>(
fd: &Fd,
fd: Fd,
offset: libc::off_t,
len: libc::off_t,
advice: PosixFadviseAdvice,
Expand Down Expand Up @@ -950,7 +952,7 @@ mod posix_fadvise {
target_os = "freebsd"
))]
pub fn posix_fallocate<Fd: AsFd>(
fd: &Fd,
fd: Fd,
offset: libc::off_t,
len: libc::off_t,
) -> Result<()> {
Expand Down
2 changes: 1 addition & 1 deletion src/kmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ libc_bitflags!(
///
/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
pub fn finit_module<Fd: AsFd>(
fd: &Fd,
fd: Fd,
param_values: &CStr,
flags: ModuleInitFlags,
) -> Result<()> {
Expand Down
32 changes: 22 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ pub mod unistd;
use std::ffi::{CStr, CString, OsStr};
use std::mem::MaybeUninit;
use std::os::unix::ffi::OsStrExt;
#[cfg(not(target_os = "redox"))]
use std::os::unix::io::BorrowedFd;
use std::os::unix::io::{AsFd, AsRawFd, RawFd};
use std::path::{Path, PathBuf};
use std::{ptr, result, slice};

Expand All @@ -184,16 +183,29 @@ pub type Result<T> = result::Result<T, Errno>;
/// ones.
pub type Error = Errno;

/// A file descriptor representing the current working directory.
/// A trait that models requirements for path file descriptors.
pub trait AsPathFd {
/// Extracts the raw file descriptor.
fn as_path_fd(&self) -> RawFd;
}

impl<Fd: AsFd> AsPathFd for Fd {
fn as_path_fd(&self) -> RawFd {
self.as_fd().as_raw_fd()
}
}

/// The `AT_FDCWD` marker FD.
#[cfg(not(target_os = "redox"))]
#[derive(Copy, Clone, Debug)]
pub struct Cwd;

#[cfg(not(target_os = "redox"))]
pub const AT_FDCWD: &BorrowedFd<'static> = unsafe {
&BorrowedFd::borrow_raw(if cfg!(target_os = "haiku") {
// Hack to work around BorrowedFd not allowing -1
-2
} else {
impl AsPathFd for Cwd {
fn as_path_fd(&self) -> RawFd {
libc::AT_FDCWD
})
};
}
}

/// Common trait used to represent file system paths by many Nix functions.
pub trait NixPath {
Expand Down
Loading

0 comments on commit 4ca7899

Please sign in to comment.