Skip to content

Commit bcd6951

Browse files
feat: I/O safety pipe, pipe2 & write
1 parent 842142f commit bcd6951

File tree

11 files changed

+58
-94
lines changed

11 files changed

+58
-94
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/sys/test_socket.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,6 @@ pub fn test_scm_rights() {
770770
.unwrap(),
771771
5
772772
);
773-
close(r).unwrap();
774773
}
775774

776775
{
@@ -803,12 +802,11 @@ pub fn test_scm_rights() {
803802

804803
let received_r = received_r.expect("Did not receive passed fd");
805804
// Ensure that the received file descriptor works
806-
write(w.as_raw_fd(), b"world").unwrap();
805+
write(&w, b"world").unwrap();
807806
let mut buf = [0u8; 5];
808807
read(received_r.as_raw_fd(), &mut buf).unwrap();
809808
assert_eq!(&buf[..], b"world");
810809
close(received_r).unwrap();
811-
close(w).unwrap();
812810
}
813811

814812
// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
@@ -1467,7 +1465,6 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
14671465
.unwrap(),
14681466
5
14691467
);
1470-
close(r).unwrap();
14711468
}
14721469

14731470
{
@@ -1510,12 +1507,11 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
15101507

15111508
let received_r = received_r.expect("Did not receive passed fd");
15121509
// Ensure that the received file descriptor works
1513-
write(w.as_raw_fd(), b"world").unwrap();
1510+
write(&w, b"world").unwrap();
15141511
let mut buf = [0u8; 5];
15151512
read(received_r.as_raw_fd(), &mut buf).unwrap();
15161513
assert_eq!(&buf[..], b"world");
15171514
close(received_r).unwrap();
1518-
close(w).unwrap();
15191515
}
15201516

15211517
// Test creating and using named unix domain sockets

test/sys/test_uio.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ fn test_process_vm_readv() {
230230
use nix::sys::signal::*;
231231
use nix::sys::wait::*;
232232
use nix::unistd::ForkResult::*;
233+
use std::os::unix::io::AsRawFd;
233234

234235
require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
235236
let _m = crate::FORK_MTX.lock();
@@ -241,10 +242,10 @@ fn test_process_vm_readv() {
241242
let (r, w) = pipe().unwrap();
242243
match unsafe { fork() }.expect("Error: Fork Failed") {
243244
Parent { child } => {
244-
close(w).unwrap();
245+
drop(w);
245246
// wait for child
246-
read(r, &mut [0u8]).unwrap();
247-
close(r).unwrap();
247+
read(r.as_raw_fd(), &mut [0u8]).unwrap();
248+
drop(r);
248249

249250
let ptr = vector.as_ptr() as usize;
250251
let remote_iov = RemoteIoVec { base: ptr, len: 5 };
@@ -263,12 +264,12 @@ fn test_process_vm_readv() {
263264
assert_eq!(20u8, buf.iter().sum());
264265
}
265266
Child => {
266-
let _ = close(r);
267+
drop(r);
267268
for i in &mut vector {
268269
*i += 1;
269270
}
270271
let _ = write(w, b"\0");
271-
let _ = close(w);
272+
drop(w);
272273
loop {
273274
pause();
274275
}

test/test_fcntl.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,9 @@ mod linux_android {
309309
assert_eq!(2, res);
310310

311311
let mut buf = [0u8; 1024];
312-
assert_eq!(2, read(rd, &mut buf).unwrap());
312+
assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
313313
assert_eq!(b"f1", &buf[0..2]);
314314
assert_eq!(7, offset);
315-
316-
close(rd).unwrap();
317-
close(wr).unwrap();
318315
}
319316

320317
#[test]
@@ -336,11 +333,6 @@ mod linux_android {
336333
// Check all the bytes are still at rd1.
337334
assert_eq!(3, read(rd1, &mut buf).unwrap());
338335
assert_eq!(b"abc", &buf[0..3]);
339-
340-
close(rd1).unwrap();
341-
close(wr1).unwrap();
342-
close(rd2).unwrap();
343-
close(wr2).unwrap();
344336
}
345337

346338
#[test]
@@ -357,11 +349,8 @@ mod linux_android {
357349

358350
// Check the bytes can be read at rd.
359351
let mut buf = [0u8; 32];
360-
assert_eq!(6, read(rd, &mut buf).unwrap());
352+
assert_eq!(6, read(rd.as_raw_fd(), &mut buf).unwrap());
361353
assert_eq!(b"abcdef", &buf[0..6]);
362-
363-
close(rd).unwrap();
364-
close(wr).unwrap();
365354
}
366355

367356
#[cfg(target_os = "linux")]
@@ -509,7 +498,7 @@ mod test_posix_fadvise {
509498
fn test_errno() {
510499
let (rd, _wr) = pipe().unwrap();
511500
let res = posix_fadvise(
512-
rd as RawFd,
501+
rd.as_raw_fd(),
513502
0,
514503
100,
515504
PosixFadviseAdvice::POSIX_FADV_WILLNEED,
@@ -565,7 +554,7 @@ mod test_posix_fallocate {
565554
#[test]
566555
fn errno() {
567556
let (rd, _wr) = pipe().unwrap();
568-
let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
557+
let err = posix_fallocate(rd.as_raw_fd(), 0, 100).unwrap_err();
569558
match err {
570559
Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
571560
errno => panic!("unexpected errno {errno}",),

test/test_poll.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@ macro_rules! loop_while_eintr {
2020
#[test]
2121
fn test_poll() {
2222
let (r, w) = pipe().unwrap();
23-
let r = unsafe { OwnedFd::from_raw_fd(r) };
2423
let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
2524

2625
// Poll an idle pipe. Should timeout
2726
let nfds = loop_while_eintr!(poll(&mut fds, 100));
2827
assert_eq!(nfds, 0);
2928
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
3029

31-
write(w, b".").unwrap();
30+
write(&w, b".").unwrap();
3231

3332
// Poll a readable pipe. Should return an event.
3433
let nfds = poll(&mut fds, 100).unwrap();
3534
assert_eq!(nfds, 1);
3635
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
37-
close(w).unwrap();
3836
}
3937

4038
// ppoll(2) is the same as poll except for how it handles timeouts and signals.
@@ -54,7 +52,6 @@ fn test_ppoll() {
5452

5553
let timeout = TimeSpec::milliseconds(1);
5654
let (r, w) = pipe().unwrap();
57-
let r = unsafe { OwnedFd::from_raw_fd(r) };
5855
let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
5956

6057
// Poll an idle pipe. Should timeout
@@ -63,13 +60,12 @@ fn test_ppoll() {
6360
assert_eq!(nfds, 0);
6461
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
6562

66-
write(w, b".").unwrap();
63+
write(&w, b".").unwrap();
6764

6865
// Poll a readable pipe. Should return an event.
6966
let nfds = ppoll(&mut fds, Some(timeout), None).unwrap();
7067
assert_eq!(nfds, 1);
7168
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
72-
close(w).unwrap();
7369
}
7470

7571
#[test]

0 commit comments

Comments
 (0)