Skip to content

Commit 3ccbad5

Browse files
feat: I/O safety pipe & pipe2
1 parent 981dc1c commit 3ccbad5

File tree

5 files changed

+34
-39
lines changed

5 files changed

+34
-39
lines changed

src/pty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl io::Read for PtyMaster {
7171

7272
impl io::Write for PtyMaster {
7373
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
74-
unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
74+
unistd::write(&self.0, buf).map_err(io::Error::from)
7575
}
7676
fn flush(&mut self) -> io::Result<()> {
7777
Ok(())
@@ -86,7 +86,7 @@ impl io::Read for &PtyMaster {
8686

8787
impl io::Write for &PtyMaster {
8888
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
89-
unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
89+
unistd::write(&self.0, buf).map_err(io::Error::from)
9090
}
9191
fn flush(&mut self) -> io::Result<()> {
9292
Ok(())

src/sys/select.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,8 @@ where
322322
mod tests {
323323
use super::*;
324324
use crate::sys::time::{TimeVal, TimeValLike};
325-
use crate::unistd::{close, pipe, write};
326-
use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
325+
use crate::unistd::{pipe, write};
326+
use std::os::unix::io::RawFd;
327327

328328
#[test]
329329
fn fdset_insert() {
@@ -466,12 +466,9 @@ mod tests {
466466
#[test]
467467
fn test_select() {
468468
let (r1, w1) = pipe().unwrap();
469-
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
470-
let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
471469
let (r2, _w2) = pipe().unwrap();
472-
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
473470

474-
write(w1.as_raw_fd(), b"hi!").unwrap();
471+
write(&w1, b"hi!").unwrap();
475472
let mut fd_set = FdSet::new();
476473
fd_set.insert(&r1);
477474
fd_set.insert(&r2);
@@ -483,18 +480,14 @@ mod tests {
483480
);
484481
assert!(fd_set.contains(&r1));
485482
assert!(!fd_set.contains(&r2));
486-
close(_w2).unwrap();
487483
}
488484

489485
#[test]
490486
fn test_select_nfds() {
491487
let (r1, w1) = pipe().unwrap();
492488
let (r2, _w2) = pipe().unwrap();
493-
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
494-
let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
495-
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
496489

497-
write(w1.as_raw_fd(), b"hi!").unwrap();
490+
write(&w1, b"hi!").unwrap();
498491
let mut fd_set = FdSet::new();
499492
fd_set.insert(&r1);
500493
fd_set.insert(&r2);
@@ -521,16 +514,13 @@ mod tests {
521514
}
522515
assert!(fd_set.contains(&r1));
523516
assert!(!fd_set.contains(&r2));
524-
close(_w2).unwrap();
525517
}
526518

527519
#[test]
528520
fn test_select_nfds2() {
529521
let (r1, w1) = pipe().unwrap();
530-
write(w1, b"hi!").unwrap();
522+
write(&w1, b"hi!").unwrap();
531523
let (r2, _w2) = pipe().unwrap();
532-
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
533-
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
534524
let mut fd_set = FdSet::new();
535525
fd_set.insert(&r1);
536526
fd_set.insert(&r2);
@@ -549,6 +539,5 @@ mod tests {
549539
);
550540
assert!(fd_set.contains(&r1));
551541
assert!(!fd_set.contains(&r2));
552-
close(_w2).unwrap();
553542
}
554543
}

src/unistd.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use std::ffi::{CString, OsStr};
3535
use std::os::unix::ffi::OsStrExt;
3636
use std::os::unix::ffi::OsStringExt;
3737
use std::os::unix::io::RawFd;
38-
use std::os::unix::io::{AsFd, AsRawFd};
38+
use std::os::unix::io::{AsFd, AsRawFd, OwnedFd};
3939
use std::path::PathBuf;
4040
use std::{fmt, mem, ptr};
4141

@@ -1115,9 +1115,13 @@ pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
11151115
/// Write to a raw file descriptor.
11161116
///
11171117
/// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
1118-
pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
1118+
pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> Result<usize> {
11191119
let res = unsafe {
1120-
libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t)
1120+
libc::write(
1121+
fd.as_fd().as_raw_fd(),
1122+
buf.as_ptr() as *const c_void,
1123+
buf.len() as size_t,
1124+
)
11211125
};
11221126

11231127
Errno::result(res).map(|r| r as usize)
@@ -1189,14 +1193,15 @@ pub fn lseek64(
11891193
/// Create an interprocess channel.
11901194
///
11911195
/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
1192-
pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> {
1193-
let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
1196+
pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> {
1197+
let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
11941198

11951199
let res = unsafe { libc::pipe(fds.as_mut_ptr() as *mut c_int) };
11961200

11971201
Error::result(res)?;
11981202

1199-
unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
1203+
let [read, write] = unsafe { fds.assume_init() };
1204+
Ok((read, write))
12001205
}
12011206

12021207
feature! {
@@ -1230,15 +1235,16 @@ feature! {
12301235
target_os = "openbsd",
12311236
target_os = "solaris"
12321237
))]
1233-
pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
1234-
let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
1238+
pub fn pipe2(flags: OFlag) -> Result<(OwnedFd, OwnedFd)> {
1239+
let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
12351240

12361241
let res =
12371242
unsafe { libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) };
12381243

12391244
Errno::result(res)?;
12401245

1241-
unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
1246+
let [read, write] = unsafe { fds.assume_init() };
1247+
Ok((read, write))
12421248
}
12431249

12441250
/// Truncate a file to a specified length

test/sys/test_select.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ pub fn test_pselect() {
99
let _mtx = crate::SIGNAL_MTX.lock();
1010

1111
let (r1, w1) = pipe().unwrap();
12-
write(w1, b"hi!").unwrap();
13-
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
12+
write(&w1, b"hi!").unwrap();
1413
let (r2, _w2) = pipe().unwrap();
15-
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
1614

1715
let mut fd_set = FdSet::new();
1816
fd_set.insert(&r1);
@@ -31,10 +29,8 @@ pub fn test_pselect() {
3129
#[test]
3230
pub fn test_pselect_nfds2() {
3331
let (r1, w1) = pipe().unwrap();
34-
write(w1, b"hi!").unwrap();
35-
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
32+
write(&w1, b"hi!").unwrap();
3633
let (r2, _w2) = pipe().unwrap();
37-
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
3834

3935
let mut fd_set = FdSet::new();
4036
fd_set.insert(&r1);

test/test_unistd.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ macro_rules! execve_test_factory (
356356
match unsafe{fork()}.unwrap() {
357357
Child => {
358358
// Make `writer` be the stdout of the new process.
359-
dup2(writer, 1).unwrap();
359+
dup2(writer.as_raw_fd(), 1).unwrap();
360360
let r = syscall();
361361
let _ = std::io::stderr()
362362
.write_all(format!("{:?}", r).as_bytes());
@@ -370,7 +370,7 @@ macro_rules! execve_test_factory (
370370
assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
371371
// Read 1024 bytes.
372372
let mut buf = [0u8; 1024];
373-
read(reader, &mut buf).unwrap();
373+
read(reader.as_raw_fd(), &mut buf).unwrap();
374374
// It should contain the things we printed using `/bin/sh`.
375375
let string = String::from_utf8_lossy(&buf);
376376
assert!(string.contains("nix!!!"));
@@ -714,12 +714,12 @@ fn test_getresgid() {
714714
fn test_pipe() {
715715
let (fd0, fd1) = pipe().unwrap();
716716
let m0 = stat::SFlag::from_bits_truncate(
717-
stat::fstat(fd0).unwrap().st_mode as mode_t,
717+
stat::fstat(fd0.as_raw_fd()).unwrap().st_mode as mode_t,
718718
);
719719
// S_IFIFO means it's a pipe
720720
assert_eq!(m0, SFlag::S_IFIFO);
721721
let m1 = stat::SFlag::from_bits_truncate(
722-
stat::fstat(fd1).unwrap().st_mode as mode_t,
722+
stat::fstat(fd1.as_raw_fd()).unwrap().st_mode as mode_t,
723723
);
724724
assert_eq!(m1, SFlag::S_IFIFO);
725725
}
@@ -743,9 +743,13 @@ fn test_pipe2() {
743743
use nix::fcntl::{fcntl, FcntlArg, FdFlag};
744744

745745
let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
746-
let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
746+
let f0 = FdFlag::from_bits_truncate(
747+
fcntl(fd0.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
748+
);
747749
assert!(f0.contains(FdFlag::FD_CLOEXEC));
748-
let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
750+
let f1 = FdFlag::from_bits_truncate(
751+
fcntl(fd1.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
752+
);
749753
assert!(f1.contains(FdFlag::FD_CLOEXEC));
750754
}
751755

0 commit comments

Comments
 (0)