Skip to content

Commit 3a11e20

Browse files
committed
Support type-safe path FDs
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
1 parent 50dc2ef commit 3a11e20

18 files changed

+197
-174
lines changed

src/dir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Dir {
4545

4646
/// Opens the given path as with `fcntl::openat`.
4747
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
48-
dirfd: &Fd,
48+
dirfd: Fd,
4949
path: &P,
5050
oflag: OFlag,
5151
mode: sys::stat::Mode,

src/fcntl.rs

+28-27
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::os::unix::io::FromRawFd;
99
use std::os::unix::io::OwnedFd;
1010
use std::os::unix::io::RawFd;
1111

12+
use crate::IntoPathFd;
1213
#[cfg(feature = "fs")]
1314
use crate::{sys::stat::Mode, NixPath, Result};
1415
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -211,15 +212,15 @@ pub fn open<P: ?Sized + NixPath>(
211212
// The conversion is not identical on all operating systems.
212213
#[allow(clippy::useless_conversion)]
213214
#[cfg(not(target_os = "redox"))]
214-
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
215-
dirfd: &Fd,
215+
pub fn openat<Fd: IntoPathFd, P: ?Sized + NixPath>(
216+
dirfd: Fd,
216217
path: &P,
217218
oflag: OFlag,
218219
mode: Mode,
219220
) -> Result<OwnedFd> {
220221
let fd = path.with_nix_path(|cstr| unsafe {
221222
libc::openat(
222-
dirfd.as_fd().as_raw_fd(),
223+
dirfd.as_raw_path_fd(),
223224
cstr.as_ptr(),
224225
oflag.bits(),
225226
mode.bits() as c_uint,
@@ -230,18 +231,18 @@ pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
230231
}
231232

232233
#[cfg(not(target_os = "redox"))]
233-
pub fn renameat<Fd1: AsFd, P1: ?Sized + NixPath, Fd2: AsFd, P2: ?Sized + NixPath>(
234-
old_dirfd: &Fd1,
234+
pub fn renameat<Fd1: IntoPathFd, P1: ?Sized + NixPath, Fd2: IntoPathFd, P2: ?Sized + NixPath>(
235+
old_dirfd: Fd1,
235236
old_path: &P1,
236-
new_dirfd: &Fd2,
237+
new_dirfd: Fd2,
237238
new_path: &P2,
238239
) -> Result<()> {
239240
let res = old_path.with_nix_path(|old_cstr| {
240241
new_path.with_nix_path(|new_cstr| unsafe {
241242
libc::renameat(
242-
old_dirfd.as_fd().as_raw_fd(),
243+
old_dirfd.as_raw_path_fd(),
243244
old_cstr.as_ptr(),
244-
new_dirfd.as_fd().as_raw_fd(),
245+
new_dirfd.as_raw_path_fd(),
245246
new_cstr.as_ptr(),
246247
)
247248
})
@@ -264,19 +265,19 @@ libc_bitflags! {
264265
feature! {
265266
#![feature = "fs"]
266267
#[cfg(all(target_os = "linux", target_env = "gnu"))]
267-
pub fn renameat2<Fd1: AsFd, P1: ?Sized + NixPath, Fd2: AsFd, P2: ?Sized + NixPath>(
268-
old_dirfd: &Fd1,
268+
pub fn renameat2<Fd1: IntoPathFd, P1: ?Sized + NixPath, Fd2: IntoPathFd, P2: ?Sized + NixPath>(
269+
old_dirfd: Fd1,
269270
old_path: &P1,
270-
new_dirfd: &Fd2,
271+
new_dirfd: Fd2,
271272
new_path: &P2,
272273
flags: RenameFlags,
273274
) -> Result<()> {
274275
let res = old_path.with_nix_path(|old_cstr| {
275276
new_path.with_nix_path(|new_cstr| unsafe {
276277
libc::renameat2(
277-
old_dirfd.as_fd().as_raw_fd(),
278+
old_dirfd.as_raw_path_fd(),
278279
old_cstr.as_ptr(),
279-
new_dirfd.as_fd().as_raw_fd(),
280+
new_dirfd.as_raw_path_fd(),
280281
new_cstr.as_ptr(),
281282
flags.bits(),
282283
)
@@ -404,10 +405,10 @@ pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
404405

405406
#[cfg(not(target_os = "redox"))]
406407
pub fn readlinkat<Fd: AsFd, P: ?Sized + NixPath>(
407-
dirfd: &Fd,
408+
dirfd: Fd,
408409
path: &P,
409410
) -> Result<OsString> {
410-
inner_readlink(Some(dirfd), path)
411+
inner_readlink(Some(&dirfd), path)
411412
}
412413
}
413414

@@ -599,9 +600,9 @@ feature! {
599600
/// returned.
600601
#[cfg(any(target_os = "android", target_os = "linux"))]
601602
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
602-
fd_in: &Fd1,
603+
fd_in: Fd1,
603604
off_in: Option<&mut libc::loff_t>,
604-
fd_out: &Fd2,
605+
fd_out: Fd2,
605606
off_out: Option<&mut libc::loff_t>,
606607
len: usize,
607608
) -> Result<usize> {
@@ -628,9 +629,9 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
628629

629630
#[cfg(any(target_os = "linux", target_os = "android"))]
630631
pub fn splice<Fd1: AsFd, Fd2: AsFd>(
631-
fd_in: &Fd1,
632+
fd_in: Fd1,
632633
off_in: Option<&mut libc::loff_t>,
633-
fd_out: &Fd2,
634+
fd_out: Fd2,
634635
off_out: Option<&mut libc::loff_t>,
635636
len: usize,
636637
flags: SpliceFFlags,
@@ -657,8 +658,8 @@ pub fn splice<Fd1: AsFd, Fd2: AsFd>(
657658

658659
#[cfg(any(target_os = "linux", target_os = "android"))]
659660
pub fn tee<Fd1: AsFd, Fd2: AsFd>(
660-
fd_in: &Fd1,
661-
fd_out: &Fd2,
661+
fd_in: Fd1,
662+
fd_out: Fd2,
662663
len: usize,
663664
flags: SpliceFFlags,
664665
) -> Result<usize> {
@@ -675,7 +676,7 @@ pub fn tee<Fd1: AsFd, Fd2: AsFd>(
675676

676677
#[cfg(any(target_os = "linux", target_os = "android"))]
677678
pub fn vmsplice<Fd: AsFd>(
678-
fd: &Fd,
679+
fd: Fd,
679680
iov: &[std::io::IoSlice<'_>],
680681
flags: SpliceFFlags,
681682
) -> Result<usize> {
@@ -734,7 +735,7 @@ feature! {
734735
#[cfg(any(target_os = "linux"))]
735736
#[cfg(feature = "fs")]
736737
pub fn fallocate<Fd: AsFd>(
737-
fd: &Fd,
738+
fd: Fd,
738739
mode: FallocateFlags,
739740
offset: libc::off_t,
740741
len: libc::off_t,
@@ -810,7 +811,7 @@ impl SpacectlRange {
810811
/// ```
811812
#[cfg(target_os = "freebsd")]
812813
pub fn fspacectl<Fd: AsFd>(
813-
fd: &Fd,
814+
fd: Fd,
814815
range: SpacectlRange,
815816
) -> Result<SpacectlRange> {
816817
let mut rqsr = libc::spacectl_range {
@@ -861,7 +862,7 @@ pub fn fspacectl<Fd: AsFd>(
861862
/// ```
862863
#[cfg(target_os = "freebsd")]
863864
pub fn fspacectl_all<Fd: AsFd>(
864-
fd: &Fd,
865+
fd: Fd,
865866
offset: libc::off_t,
866867
len: libc::off_t,
867868
) -> Result<()> {
@@ -917,7 +918,7 @@ mod posix_fadvise {
917918
feature! {
918919
#![feature = "fs"]
919920
pub fn posix_fadvise<Fd: AsFd>(
920-
fd: &Fd,
921+
fd: Fd,
921922
offset: libc::off_t,
922923
len: libc::off_t,
923924
advice: PosixFadviseAdvice,
@@ -950,7 +951,7 @@ mod posix_fadvise {
950951
target_os = "freebsd"
951952
))]
952953
pub fn posix_fallocate<Fd: AsFd>(
953-
fd: &Fd,
954+
fd: Fd,
954955
offset: libc::off_t,
955956
len: libc::off_t,
956957
) -> Result<()> {

src/kmod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ libc_bitflags!(
8080
///
8181
/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
8282
pub fn finit_module<Fd: AsFd>(
83-
fd: &Fd,
83+
fd: Fd,
8484
param_values: &CStr,
8585
flags: ModuleInitFlags,
8686
) -> Result<()> {

src/lib.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ pub mod unistd;
162162
use std::ffi::{CStr, CString, OsStr};
163163
use std::mem::MaybeUninit;
164164
use std::os::unix::ffi::OsStrExt;
165-
#[cfg(not(target_os = "redox"))]
166-
use std::os::unix::io::BorrowedFd;
165+
use std::os::unix::io::{AsFd, AsRawFd, RawFd};
167166
use std::path::{Path, PathBuf};
168167
use std::{ptr, result, slice};
169168

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

187-
/// A file descriptor representing the current working directory.
186+
/// A trait that models requirements for path file descriptors.
187+
pub trait IntoPathFd {
188+
/// Extracts the raw file descriptor.
189+
fn as_raw_path_fd(&self) -> RawFd;
190+
}
191+
192+
impl<Fd: AsFd> IntoPathFd for Fd {
193+
fn as_raw_path_fd(&self) -> RawFd {
194+
self.as_fd().as_raw_fd()
195+
}
196+
}
197+
198+
/// The `AT_FDCWD` marker FD.
199+
#[cfg(not(target_os = "redox"))]
200+
#[derive(Copy, Clone, Debug)]
201+
pub struct Cwd;
202+
188203
#[cfg(not(target_os = "redox"))]
189-
pub const AT_FDCWD: &BorrowedFd<'static> = unsafe {
190-
&BorrowedFd::borrow_raw(if cfg!(target_os = "haiku") {
191-
// Hack to work around BorrowedFd not allowing -1
192-
-2
193-
} else {
204+
impl IntoPathFd for Cwd {
205+
fn as_raw_path_fd(&self) -> RawFd {
194206
libc::AT_FDCWD
195-
})
196-
};
207+
}
208+
}
197209

198210
/// Common trait used to represent file system paths by many Nix functions.
199211
pub trait NixPath {

src/pty.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@ impl Drop for PtyMaster {
8181

8282
impl io::Read for PtyMaster {
8383
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
84-
unistd::read(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf)
84+
unistd::read(unsafe { BorrowedFd::borrow_raw(self.0) }, buf)
8585
.map_err(io::Error::from)
8686
}
8787
}
8888

8989
impl io::Write for PtyMaster {
9090
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
91-
unistd::write(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf)
91+
unistd::write(unsafe { BorrowedFd::borrow_raw(self.0) }, buf)
9292
.map_err(io::Error::from)
9393
}
9494
fn flush(&mut self) -> io::Result<()> {
@@ -98,14 +98,14 @@ impl io::Write for PtyMaster {
9898

9999
impl io::Read for &PtyMaster {
100100
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
101-
unistd::read(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf)
101+
unistd::read(unsafe { BorrowedFd::borrow_raw(self.0) }, buf)
102102
.map_err(io::Error::from)
103103
}
104104
}
105105

106106
impl io::Write for &PtyMaster {
107107
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
108-
unistd::write(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf)
108+
unistd::write(unsafe { BorrowedFd::borrow_raw(self.0) }, buf)
109109
.map_err(io::Error::from)
110110
}
111111
fn flush(&mut self) -> io::Result<()> {

0 commit comments

Comments
 (0)