1 use cfg_if::cfg_if;
2 
3 #[macro_export] macro_rules! skip {
4     ($($reason: expr),+) => {
5         use ::std::io::{self, Write};
6 
7         let stderr = io::stderr();
8         let mut handle = stderr.lock();
9         writeln!(handle, $($reason),+).unwrap();
10         return;
11     }
12 }
13 
14 cfg_if! {
15     if #[cfg(any(target_os = "android", target_os = "linux"))] {
16         #[macro_export] macro_rules! require_capability {
17             ($capname:ident) => {
18                 use ::caps::{Capability, CapSet, has_cap};
19 
20                 if !has_cap(None, CapSet::Effective, Capability::$capname)
21                     .unwrap()
22                 {
23                     skip!("Insufficient capabilities. Skipping test.");
24                 }
25             }
26         }
27     } else if #[cfg(not(target_os = "redox"))] {
28         #[macro_export] macro_rules! require_capability {
29             ($capname:ident) => {}
30         }
31     }
32 }
33 
34 #[cfg(any(target_os = "linux", target_os= "android"))]
35 #[macro_export] macro_rules! skip_if_cirrus {
36     ($reason:expr) => {
37         if std::env::var_os("CIRRUS_CI").is_some() {
38             skip!("{}", $reason);
39         }
40     }
41 }
42 
43 #[cfg(target_os = "freebsd")]
44 #[macro_export] macro_rules! skip_if_jailed {
45     ($name:expr) => {
46         use ::sysctl::CtlValue;
47 
48         if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
49             .unwrap()
50         {
51             skip!("{} cannot run in a jail. Skipping test.", $name);
52         }
53     }
54 }
55 
56 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
57 #[macro_export] macro_rules! skip_if_not_root {
58     ($name:expr) => {
59         use nix::unistd::Uid;
60 
61         if !Uid::current().is_root() {
62             skip!("{} requires root privileges. Skipping test.", $name);
63         }
64     };
65 }
66 
67 cfg_if! {
68     if #[cfg(any(target_os = "android", target_os = "linux"))] {
69         #[macro_export] macro_rules! skip_if_seccomp {
70             ($name:expr) => {
71                 if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
72                     for l in s.lines() {
73                         let mut fields = l.split_whitespace();
74                         if fields.next() == Some("Seccomp:") &&
75                             fields.next() != Some("0")
76                         {
77                             skip!("{} cannot be run in Seccomp mode.  Skipping test.",
78                                 stringify!($name));
79                         }
80                     }
81                 }
82             }
83         }
84     } else if #[cfg(not(target_os = "redox"))] {
85         #[macro_export] macro_rules! skip_if_seccomp {
86             ($name:expr) => {}
87         }
88     }
89 }
90 
91 cfg_if! {
92     if #[cfg(target_os = "linux")] {
93         #[macro_export] macro_rules! require_kernel_version {
94             ($name:expr, $version_requirement:expr) => {
95                 use semver::{Version, VersionReq};
96 
97                 let version_requirement = VersionReq::parse($version_requirement)
98                         .expect("Bad match_version provided");
99 
100                 let uname = nix::sys::utsname::uname();
101                 println!("{}", uname.sysname());
102                 println!("{}", uname.nodename());
103                 println!("{}", uname.release());
104                 println!("{}", uname.version());
105                 println!("{}", uname.machine());
106 
107                 // Fix stuff that the semver parser can't handle
108                 let fixed_release = &uname.release().to_string()
109                     // Fedora 33 reports version as 4.18.el8_2.x86_64 or
110                     // 5.18.200-fc33.x86_64.  Remove the underscore.
111                     .replace("_", "-")
112                     // Cirrus-CI reports version as 4.19.112+ .  Remove the +
113                     .replace("+", "");
114                 let mut version = Version::parse(fixed_release).unwrap();
115 
116                 //Keep only numeric parts
117                 version.pre = semver::Prerelease::EMPTY;
118                 version.build = semver::BuildMetadata::EMPTY;
119 
120                 if !version_requirement.matches(&version) {
121                     skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
122                         stringify!($name), version, version_requirement);
123                 }
124             }
125         }
126     }
127 }
128