1#[macro_use]
2extern crate cfg_if;
3#[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)]
4extern crate nix;
5
6mod common;
7mod sys;
8#[cfg(not(target_os = "redox"))]
9mod test_dir;
10mod test_fcntl;
11#[cfg(any(target_os = "android", target_os = "linux"))]
12mod test_kmod;
13#[cfg(any(
14 target_os = "dragonfly",
15 target_os = "freebsd",
16 target_os = "fushsia",
17 target_os = "linux",
18 target_os = "netbsd"
19))]
20mod test_mq;
21#[cfg(not(target_os = "redox"))]
22mod test_net;
23mod test_nix_path;
24#[cfg(target_os = "freebsd")]
25mod test_nmount;
26mod test_poll;
27#[cfg(not(any(
28 target_os = "redox",
29 target_os = "fuchsia",
30 target_os = "haiku"
31)))]
32mod test_pty;
33mod test_resource;
34#[cfg(any(
35 target_os = "android",
36 target_os = "dragonfly",
37 all(target_os = "freebsd", fbsd14),
38 target_os = "linux"
39))]
40mod test_sched;
41#[cfg(any(
42 target_os = "android",
43 target_os = "dragonfly",
44 target_os = "freebsd",
45 target_os = "ios",
46 target_os = "linux",
47 target_os = "macos"
48))]
49mod test_sendfile;
50mod test_stat;
51mod test_time;
52#[cfg(all(
53 any(
54 target_os = "freebsd",
55 target_os = "illumos",
56 target_os = "linux",
57 target_os = "netbsd"
58 ),
59 feature = "time",
60 feature = "signal"
61))]
62mod test_timer;
63mod test_unistd;
64
65use nix::unistd::{chdir, getcwd, read};
66use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
67use std::os::unix::io::{AsFd, AsRawFd};
68use std::path::PathBuf;
69
70/// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s
71fn read_exact<Fd: AsFd>(f: Fd, buf: &mut [u8]) {
72 let mut len = 0;
73 while len < buf.len() {
74 // get_mut would be better than split_at_mut, but it requires nightly
75 let (_, remaining) = buf.split_at_mut(len);
76 len += read(f.as_fd().as_raw_fd(), remaining).unwrap();
77 }
78}
79
80/// Any test that creates child processes must grab this mutex, regardless
81/// of what it does with those children.
82pub static FORK_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(());
83/// Any test that changes the process's current working directory must grab
84/// the RwLock exclusively. Any process that cares about the current
85/// working directory must grab it shared.
86pub static CWD_LOCK: RwLock<()> = RwLock::new(());
87/// Any test that changes the process's supplementary groups must grab this
88/// mutex
89pub static GROUPS_MTX: Mutex<()> = Mutex::new(());
90/// Any tests that loads or unloads kernel modules must grab this mutex
91pub static KMOD_MTX: Mutex<()> = Mutex::new(());
92/// Any test that calls ptsname(3) must grab this mutex.
93pub static PTSNAME_MTX: Mutex<()> = Mutex::new(());
94/// Any test that alters signal handling must grab this mutex.
95pub static SIGNAL_MTX: Mutex<()> = Mutex::new(());
96
97/// RAII object that restores a test's original directory on drop
98struct DirRestore<'a> {
99 d: PathBuf,
100 _g: RwLockWriteGuard<'a, ()>,
101}
102
103impl<'a> DirRestore<'a> {
104 fn new() -> Self {
105 let guard = crate::CWD_LOCK.write();
106 DirRestore {
107 _g: guard,
108 d: getcwd().unwrap(),
109 }
110 }
111}
112
113impl<'a> Drop for DirRestore<'a> {
114 fn drop(&mut self) {
115 let r = chdir(&self.d);
116 if std::thread::panicking() {
117 r.unwrap();
118 }
119 }
120}
121