1use std::io::{Read, Write};
12use std::path::PathBuf;
13
14use crate::error::ErrorKind::*;
15use crate::error::*;
16
17use crate::{ControllIdentifier, ControllerInternal, Controllers, Resources, Subsystem};
18
19#[derive(Debug, Clone)]
28pub struct FreezerController {
29 base: PathBuf,
30 path: PathBuf,
31 v2: bool,
32}
33
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub enum FreezerState {
37 Thawed,
39 Freezing,
41 Frozen,
43}
44
45impl ControllerInternal for FreezerController {
46 fn control_type(&self) -> Controllers {
47 Controllers::Freezer
48 }
49 fn get_path(&self) -> &PathBuf {
50 &self.path
51 }
52 fn get_path_mut(&mut self) -> &mut PathBuf {
53 &mut self.path
54 }
55 fn get_base(&self) -> &PathBuf {
56 &self.base
57 }
58
59 fn apply(&self, _res: &Resources) -> Result<()> {
60 Ok(())
61 }
62}
63
64impl ControllIdentifier for FreezerController {
65 fn controller_type() -> Controllers {
66 Controllers::Freezer
67 }
68}
69
70impl<'a> From<&'a Subsystem> for &'a FreezerController {
71 fn from(sub: &'a Subsystem) -> &'a FreezerController {
72 unsafe {
73 match sub {
74 Subsystem::Freezer(c) => c,
75 _ => {
76 assert_eq!(1, 0);
77 let v = std::mem::MaybeUninit::uninit();
78 v.assume_init()
79 }
80 }
81 }
82 }
83}
84
85impl FreezerController {
86 pub fn new(root: PathBuf, v2: bool) -> Self {
88 Self {
89 base: root.clone(),
90 path: root,
91 v2,
92 }
93 }
94
95 pub fn freeze(&self) -> Result<()> {
97 let mut file_name = "freezer.state";
98 let mut content = "FROZEN".to_string();
99 if self.v2 {
100 file_name = "cgroup.freeze";
101 content = "1".to_string();
102 }
103
104 self.open_path(file_name, true).and_then(|mut file| {
105 file.write_all(content.as_ref())
106 .map_err(|e| Error::with_cause(WriteFailed(file_name.to_string(), content), e))
107 })
108 }
109
110 pub fn thaw(&self) -> Result<()> {
112 let mut file_name = "freezer.state";
113 let mut content = "THAWED".to_string();
114 if self.v2 {
115 file_name = "cgroup.freeze";
116 content = "0".to_string();
117 }
118 self.open_path(file_name, true).and_then(|mut file| {
119 file.write_all(content.as_ref())
120 .map_err(|e| Error::with_cause(WriteFailed(file_name.to_string(), content), e))
121 })
122 }
123
124 pub fn state(&self) -> Result<FreezerState> {
126 let mut file_name = "freezer.state";
127 if self.v2 {
128 file_name = "cgroup.freeze";
129 }
130 self.open_path(file_name, false).and_then(|mut file| {
131 let mut s = String::new();
132 let res = file.read_to_string(&mut s);
133 match res {
134 Ok(_) => match s.trim() {
135 "FROZEN" => Ok(FreezerState::Frozen),
136 "THAWED" => Ok(FreezerState::Thawed),
137 "1" => Ok(FreezerState::Frozen),
138 "0" => Ok(FreezerState::Thawed),
139 "FREEZING" => Ok(FreezerState::Freezing),
140 _ => Err(Error::new(ParseError)),
141 },
142 Err(e) => Err(Error::with_cause(ReadFailed(file_name.to_string()), e)),
143 }
144 })
145 }
146}