Blame


1 0cde9354 2023-03-15 contact use std::{
2 0cde9354 2023-03-15 contact ffi::OsStr,
3 c6b1d112 2023-03-19 contact fs::OpenOptions,
4 c6b1d112 2023-03-19 contact io::{self, ErrorKind},
5 9b2d8449 2023-03-16 contact os::{
6 9b2d8449 2023-03-16 contact fd::{AsFd, AsRawFd, BorrowedFd},
7 f41a8ff7 2023-03-19 contact unix::{fs::OpenOptionsExt, process::ExitStatusExt},
8 9b2d8449 2023-03-16 contact },
9 0cde9354 2023-03-15 contact path::{Path, PathBuf},
10 0cde9354 2023-03-15 contact ptr::addr_of_mut,
11 eb075e35 2023-03-21 contact time::SystemTime,
12 0cde9354 2023-03-15 contact };
13 0cde9354 2023-03-15 contact
14 c6b1d112 2023-03-19 contact mod status;
15 c6b1d112 2023-03-19 contact mod tai;
16 f1abd543 2023-03-19 contact
17 c6b1d112 2023-03-19 contact use status::SvStatus;
18 c6b1d112 2023-03-19 contact
19 9b2d8449 2023-03-16 contact fn locked(fd: BorrowedFd) -> io::Result<bool> {
20 0cde9354 2023-03-15 contact let mut flock = libc::flock {
21 0cde9354 2023-03-15 contact l_type: libc::F_RDLCK as libc::c_short,
22 0cde9354 2023-03-15 contact l_whence: libc::SEEK_SET as libc::c_short,
23 0cde9354 2023-03-15 contact l_start: 0,
24 0cde9354 2023-03-15 contact l_len: 0,
25 0cde9354 2023-03-15 contact l_pid: 0,
26 0cde9354 2023-03-15 contact };
27 9b2d8449 2023-03-16 contact match unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_GETLK, addr_of_mut!(flock)) } {
28 0cde9354 2023-03-15 contact -1 => Err(io::Error::last_os_error()),
29 0cde9354 2023-03-15 contact 0 => Ok(flock.l_type != libc::F_UNLCK as libc::c_short),
30 0cde9354 2023-03-15 contact _ => todo!("fcntl() != -1 && fcntl != 0"),
31 0cde9354 2023-03-15 contact }
32 0cde9354 2023-03-15 contact }
33 0cde9354 2023-03-15 contact
34 0cde9354 2023-03-15 contact pub struct SupervisedStatus {
35 0cde9354 2023-03-15 contact pub up: bool,
36 234f6a5a 2023-03-19 contact pub wanted_up: bool,
37 234f6a5a 2023-03-19 contact pub normally_up: bool,
38 0cde9354 2023-03-15 contact pub ready: bool,
39 0cde9354 2023-03-15 contact pub paused: bool,
40 0cde9354 2023-03-15 contact pub pid: u64,
41 234f6a5a 2023-03-19 contact pub exit_code: Option<i32>,
42 0cde9354 2023-03-15 contact // signal
43 234f6a5a 2023-03-19 contact pub signal_number: Option<i32>,
44 eb075e35 2023-03-21 contact pub up_down_since: SystemTime,
45 eb075e35 2023-03-21 contact pub ready_since: SystemTime,
46 0cde9354 2023-03-15 contact }
47 0cde9354 2023-03-15 contact
48 0cde9354 2023-03-15 contact pub enum Status {
49 0cde9354 2023-03-15 contact Unsupervised,
50 0cde9354 2023-03-15 contact Supervised(SupervisedStatus),
51 0cde9354 2023-03-15 contact }
52 0cde9354 2023-03-15 contact
53 0cde9354 2023-03-15 contact pub struct ServiceDir(PathBuf);
54 0cde9354 2023-03-15 contact
55 0cde9354 2023-03-15 contact impl ServiceDir {
56 0cde9354 2023-03-15 contact pub fn name(&self) -> &OsStr {
57 0cde9354 2023-03-15 contact self.0.file_name().unwrap()
58 0cde9354 2023-03-15 contact }
59 0cde9354 2023-03-15 contact pub fn supervised(&self) -> io::Result<bool> {
60 0cde9354 2023-03-15 contact let mut path = self.0.clone();
61 0cde9354 2023-03-15 contact path.extend(["supervise", "lock"]);
62 0cde9354 2023-03-15 contact match OpenOptions::new()
63 0cde9354 2023-03-15 contact .read(true)
64 0cde9354 2023-03-15 contact .custom_flags(libc::O_NONBLOCK)
65 0cde9354 2023-03-15 contact .open(&path)
66 0cde9354 2023-03-15 contact {
67 0cde9354 2023-03-15 contact Err(err) => match err.kind() {
68 0cde9354 2023-03-15 contact ErrorKind::NotFound => Ok(false),
69 0cde9354 2023-03-15 contact _ => Err(err),
70 0cde9354 2023-03-15 contact },
71 9b2d8449 2023-03-16 contact Ok(lock) => locked(lock.as_fd()),
72 0cde9354 2023-03-15 contact }
73 0cde9354 2023-03-15 contact }
74 0cde9354 2023-03-15 contact pub fn status(&self) -> io::Result<Status> {
75 0cde9354 2023-03-15 contact if self.supervised()? {
76 0cde9354 2023-03-15 contact let mut path = self.0.clone();
77 0cde9354 2023-03-15 contact path.extend(["supervise", "status"]);
78 0cde9354 2023-03-15 contact let status = OpenOptions::new()
79 0cde9354 2023-03-15 contact .read(true)
80 0cde9354 2023-03-15 contact .custom_flags(libc::O_CLOEXEC)
81 0cde9354 2023-03-15 contact .open(&path)
82 0cde9354 2023-03-15 contact .and_then(SvStatus::try_from)?;
83 0cde9354 2023-03-15 contact assert!(path.pop());
84 0cde9354 2023-03-15 contact assert!(path.pop());
85 0cde9354 2023-03-15 contact path.push("down");
86 234f6a5a 2023-03-19 contact let normally_up = !path.try_exists()?;
87 0cde9354 2023-03-15 contact Ok(Status::Supervised(SupervisedStatus {
88 0cde9354 2023-03-15 contact up: status.pid != 0 && !status.finishing,
89 234f6a5a 2023-03-19 contact wanted_up: status.want_up,
90 234f6a5a 2023-03-19 contact normally_up,
91 0cde9354 2023-03-15 contact ready: status.pid != 0 && status.ready,
92 0cde9354 2023-03-15 contact paused: status.paused,
93 0cde9354 2023-03-15 contact pid: status.pid,
94 234f6a5a 2023-03-19 contact exit_code: if status.pid != 0 && !status.finishing {
95 0cde9354 2023-03-15 contact None
96 0cde9354 2023-03-15 contact } else {
97 234f6a5a 2023-03-19 contact status.wait_status.code()
98 0cde9354 2023-03-15 contact },
99 234f6a5a 2023-03-19 contact signal_number: if status.pid != 0 && !status.finishing {
100 0cde9354 2023-03-15 contact None
101 0cde9354 2023-03-15 contact } else {
102 234f6a5a 2023-03-19 contact status.wait_status.signal()
103 0cde9354 2023-03-15 contact },
104 234f6a5a 2023-03-19 contact up_down_since: status.stamp,
105 234f6a5a 2023-03-19 contact ready_since: status.ready_stamp,
106 0cde9354 2023-03-15 contact }))
107 0cde9354 2023-03-15 contact } else {
108 0cde9354 2023-03-15 contact Ok(Status::Unsupervised)
109 0cde9354 2023-03-15 contact }
110 0cde9354 2023-03-15 contact }
111 0cde9354 2023-03-15 contact }
112 0cde9354 2023-03-15 contact
113 0cde9354 2023-03-15 contact pub struct ScanDir(PathBuf);
114 0cde9354 2023-03-15 contact
115 0cde9354 2023-03-15 contact impl ScanDir {
116 0cde9354 2023-03-15 contact pub fn new<P: AsRef<Path>>(path: P) -> Self {
117 0cde9354 2023-03-15 contact Self(PathBuf::from(path.as_ref()))
118 0cde9354 2023-03-15 contact }
119 0cde9354 2023-03-15 contact pub fn service_dirs(&self) -> io::Result<impl Iterator<Item = ServiceDir>> {
120 0cde9354 2023-03-15 contact Ok(self.0.read_dir()?.flatten().filter_map(|entry| {
121 0cde9354 2023-03-15 contact let path = entry.path();
122 0cde9354 2023-03-15 contact if path.file_name().unwrap() == ".s6-svscan" {
123 0cde9354 2023-03-15 contact None
124 0cde9354 2023-03-15 contact } else {
125 0cde9354 2023-03-15 contact Some(ServiceDir(path))
126 0cde9354 2023-03-15 contact }
127 0cde9354 2023-03-15 contact }))
128 0cde9354 2023-03-15 contact }
129 0cde9354 2023-03-15 contact }