Skip to content

Commit c6af957

Browse files
committed
Support type-safe path FDs
Signed-off-by: Alex Saveau <[email protected]>
1 parent 30b32c4 commit c6af957

File tree

12 files changed

+160
-140
lines changed

12 files changed

+160
-140
lines changed

src/dir.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
33
use crate::errno::Errno;
44
use crate::fcntl::{self, OFlag};
5-
use crate::sys;
5+
use crate::{sys, AsDirFd};
66
use crate::{Error, NixPath, Result};
77
use cfg_if::cfg_if;
88
use std::ffi;
9-
use std::os::unix::io::AsFd;
109
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
1110
use std::ptr;
1211

@@ -44,8 +43,8 @@ impl Dir {
4443
}
4544

4645
/// Opens the given path as with `fcntl::openat`.
47-
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
48-
dirfd: &Fd,
46+
pub fn openat<Fd: AsDirFd, P: ?Sized + NixPath>(
47+
dirfd: Fd,
4948
path: &P,
5049
oflag: OFlag,
5150
mode: sys::stat::Mode,

src/fcntl.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use std::os::unix::io::FromRawFd;
99
use std::os::unix::io::OwnedFd;
1010
use std::os::unix::io::RawFd;
1111

12+
#[cfg(not(target_os = "redox"))]
13+
use crate::AsDirFd;
1214
#[cfg(feature = "fs")]
1315
use crate::{sys::stat::Mode, NixPath, Result};
1416
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -211,15 +213,15 @@ pub fn open<P: ?Sized + NixPath>(
211213
// The conversion is not identical on all operating systems.
212214
#[allow(clippy::useless_conversion)]
213215
#[cfg(not(target_os = "redox"))]
214-
pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
215-
dirfd: &Fd,
216+
pub fn openat<Fd: AsDirFd, P: ?Sized + NixPath>(
217+
dirfd: Fd,
216218
path: &P,
217219
oflag: OFlag,
218220
mode: Mode,
219221
) -> Result<OwnedFd> {
220222
let fd = path.with_nix_path(|cstr| unsafe {
221223
libc::openat(
222-
dirfd.as_fd().as_raw_fd(),
224+
dirfd.as_dir_fd(),
223225
cstr.as_ptr(),
224226
oflag.bits(),
225227
mode.bits() as c_uint,
@@ -230,18 +232,18 @@ pub fn openat<Fd: AsFd, P: ?Sized + NixPath>(
230232
}
231233

232234
#[cfg(not(target_os = "redox"))]
233-
pub fn renameat<Fd1: AsFd, P1: ?Sized + NixPath, Fd2: AsFd, P2: ?Sized + NixPath>(
234-
old_dirfd: &Fd1,
235+
pub fn renameat<Fd1: AsDirFd, P1: ?Sized + NixPath, Fd2: AsDirFd, P2: ?Sized + NixPath>(
236+
old_dirfd: Fd1,
235237
old_path: &P1,
236-
new_dirfd: &Fd2,
238+
new_dirfd: Fd2,
237239
new_path: &P2,
238240
) -> Result<()> {
239241
let res = old_path.with_nix_path(|old_cstr| {
240242
new_path.with_nix_path(|new_cstr| unsafe {
241243
libc::renameat(
242-
old_dirfd.as_fd().as_raw_fd(),
244+
old_dirfd.as_dir_fd(),
243245
old_cstr.as_ptr(),
244-
new_dirfd.as_fd().as_raw_fd(),
246+
new_dirfd.as_dir_fd(),
245247
new_cstr.as_ptr(),
246248
)
247249
})
@@ -264,19 +266,19 @@ libc_bitflags! {
264266
feature! {
265267
#![feature = "fs"]
266268
#[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,
269+
pub fn renameat2<Fd1: AsDirFd, P1: ?Sized + NixPath, Fd2: AsDirFd, P2: ?Sized + NixPath>(
270+
old_dirfd: Fd1,
269271
old_path: &P1,
270-
new_dirfd: &Fd2,
272+
new_dirfd: Fd2,
271273
new_path: &P2,
272274
flags: RenameFlags,
273275
) -> Result<()> {
274276
let res = old_path.with_nix_path(|old_cstr| {
275277
new_path.with_nix_path(|new_cstr| unsafe {
276278
libc::renameat2(
277-
old_dirfd.as_fd().as_raw_fd(),
279+
old_dirfd.as_dir_fd(),
278280
old_cstr.as_ptr(),
279-
new_dirfd.as_fd().as_raw_fd(),
281+
new_dirfd.as_dir_fd(),
280282
new_cstr.as_ptr(),
281283
flags.bits(),
282284
)
@@ -404,10 +406,10 @@ pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
404406

405407
#[cfg(not(target_os = "redox"))]
406408
pub fn readlinkat<Fd: AsFd, P: ?Sized + NixPath>(
407-
dirfd: &Fd,
409+
dirfd: Fd,
408410
path: &P,
409411
) -> Result<OsString> {
410-
inner_readlink(Some(dirfd), path)
412+
inner_readlink(Some(&dirfd), path)
411413
}
412414
}
413415

@@ -623,9 +625,9 @@ feature! {
623625
/// returned.
624626
#[cfg(any(target_os = "android", target_os = "linux"))]
625627
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
626-
fd_in: &Fd1,
628+
fd_in: Fd1,
627629
off_in: Option<&mut libc::loff_t>,
628-
fd_out: &Fd2,
630+
fd_out: Fd2,
629631
off_out: Option<&mut libc::loff_t>,
630632
len: usize,
631633
) -> Result<usize> {
@@ -652,9 +654,9 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
652654

653655
#[cfg(any(target_os = "linux", target_os = "android"))]
654656
pub fn splice<Fd1: AsFd, Fd2: AsFd>(
655-
fd_in: &Fd1,
657+
fd_in: Fd1,
656658
off_in: Option<&mut libc::loff_t>,
657-
fd_out: &Fd2,
659+
fd_out: Fd2,
658660
off_out: Option<&mut libc::loff_t>,
659661
len: usize,
660662
flags: SpliceFFlags,
@@ -681,8 +683,8 @@ pub fn splice<Fd1: AsFd, Fd2: AsFd>(
681683

682684
#[cfg(any(target_os = "linux", target_os = "android"))]
683685
pub fn tee<Fd1: AsFd, Fd2: AsFd>(
684-
fd_in: &Fd1,
685-
fd_out: &Fd2,
686+
fd_in: Fd1,
687+
fd_out: Fd2,
686688
len: usize,
687689
flags: SpliceFFlags,
688690
) -> Result<usize> {
@@ -699,7 +701,7 @@ pub fn tee<Fd1: AsFd, Fd2: AsFd>(
699701

700702
#[cfg(any(target_os = "linux", target_os = "android"))]
701703
pub fn vmsplice<Fd: AsFd>(
702-
fd: &Fd,
704+
fd: Fd,
703705
iov: &[std::io::IoSlice<'_>],
704706
flags: SpliceFFlags,
705707
) -> Result<usize> {
@@ -758,7 +760,7 @@ feature! {
758760
#[cfg(any(target_os = "linux"))]
759761
#[cfg(feature = "fs")]
760762
pub fn fallocate<Fd: AsFd>(
761-
fd: &Fd,
763+
fd: Fd,
762764
mode: FallocateFlags,
763765
offset: libc::off_t,
764766
len: libc::off_t,
@@ -834,7 +836,7 @@ impl SpacectlRange {
834836
/// ```
835837
#[cfg(target_os = "freebsd")]
836838
pub fn fspacectl<Fd: AsFd>(
837-
fd: &Fd,
839+
fd: Fd,
838840
range: SpacectlRange,
839841
) -> Result<SpacectlRange> {
840842
let mut rqsr = libc::spacectl_range {
@@ -885,7 +887,7 @@ pub fn fspacectl<Fd: AsFd>(
885887
/// ```
886888
#[cfg(target_os = "freebsd")]
887889
pub fn fspacectl_all<Fd: AsFd>(
888-
fd: &Fd,
890+
fd: Fd,
889891
offset: libc::off_t,
890892
len: libc::off_t,
891893
) -> Result<()> {
@@ -941,7 +943,7 @@ mod posix_fadvise {
941943
feature! {
942944
#![feature = "fs"]
943945
pub fn posix_fadvise<Fd: AsFd>(
944-
fd: &Fd,
946+
fd: Fd,
945947
offset: libc::off_t,
946948
len: libc::off_t,
947949
advice: PosixFadviseAdvice,
@@ -974,7 +976,7 @@ mod posix_fadvise {
974976
target_os = "freebsd"
975977
))]
976978
pub fn posix_fallocate<Fd: AsFd>(
977-
fd: &Fd,
979+
fd: Fd,
978980
offset: libc::off_t,
979981
len: libc::off_t,
980982
) -> Result<()> {

src/lib.rs

Lines changed: 33 additions & 10 deletions
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,40 @@ 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 representing directory file descriptors, to be used in the
187+
/// `*at` family of functions.
188+
pub trait AsDirFd {
189+
/// Extracts the raw file descriptor.
190+
fn as_dir_fd(&self) -> RawFd;
191+
}
192+
193+
impl<Fd: AsFd> AsDirFd for Fd {
194+
fn as_dir_fd(&self) -> RawFd {
195+
self.as_fd().as_raw_fd()
196+
}
197+
}
198+
199+
/// The `AT_FDCWD` marker file descriptor.
200+
///
201+
/// # Examples
202+
///
203+
/// ```
204+
/// # use nix::Cwd;
205+
/// # use nix::fcntl::{OFlag, openat};
206+
/// # use nix::sys::stat::Mode;
207+
///
208+
/// let file = openat(Cwd, "README.md", OFlag::O_RDONLY, Mode::empty());
209+
/// ```
210+
#[cfg(not(target_os = "redox"))]
211+
#[derive(Copy, Clone, Debug)]
212+
pub struct Cwd;
213+
188214
#[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 {
215+
impl AsDirFd for Cwd {
216+
fn as_dir_fd(&self) -> RawFd {
194217
libc::AT_FDCWD
195-
})
196-
};
218+
}
219+
}
197220

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

src/sys/epoll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl EpollEvent {
8787
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
8888
///
8989
/// // Arm eventfd & Time wait
90-
/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
90+
/// write(&eventfd, &1u64.to_ne_bytes())?;
9191
/// let now = Instant::now();
9292
///
9393
/// // Wait on event

0 commit comments

Comments
 (0)