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