1 use std::fs::File; 2 use std::io::{self, BufRead}; 3 use std::sync::{Arc, Mutex}; 4 5 use crate::error::parse_error::ParseErrorType; 6 use crate::manager::UnitManager; 7 use crate::unit::timer::TimerUnitAttr; 8 use crate::unit::{BaseUnit, Unit}; 9 use crate::DRAGON_REACH_UNIT_DIR; 10 use crate::{ 11 error::parse_error::ParseError, 12 unit::{service::ServiceUnitAttr, BaseUnitAttr, InstallUnitAttr, UnitType}, 13 }; 14 15 use hashbrown::HashMap; 16 use lazy_static::lazy_static; 17 18 use self::parse_service::ServiceParser; 19 use self::parse_target::TargetParser; 20 use self::parse_util::UnitParseUtil; 21 22 pub mod graph; 23 pub mod parse_service; 24 pub mod parse_target; 25 pub mod parse_util; 26 27 //对应Unit段类型 28 #[derive(PartialEq, Clone, Copy)] 29 pub enum Segment { 30 None, 31 Unit, 32 Install, 33 Service, 34 } 35 36 lazy_static! { 37 pub static ref UNIT_SUFFIX: HashMap<&'static str, UnitType> = { 38 let mut table = HashMap::new(); 39 table.insert("automount", UnitType::Automount); 40 table.insert("device", UnitType::Device); 41 table.insert("mount", UnitType::Mount); 42 table.insert("path", UnitType::Path); 43 table.insert("scope", UnitType::Scope); 44 table.insert("service", UnitType::Service); 45 table.insert("slice", UnitType::Automount); 46 table.insert("automount", UnitType::Slice); 47 table.insert("socket", UnitType::Socket); 48 table.insert("swap", UnitType::Swap); 49 table.insert("target", UnitType::Target); 50 table.insert("timer", UnitType::Timer); 51 table 52 }; 53 pub static ref SEGMENT_TABLE: HashMap<&'static str, Segment> = { 54 let mut table = HashMap::new(); 55 table.insert("[Unit]", Segment::Unit); 56 table.insert("[Install]", Segment::Install); 57 table.insert("[Service]", Segment::Service); 58 table 59 }; 60 pub static ref INSTALL_UNIT_ATTR_TABLE: HashMap<&'static str, InstallUnitAttr> = { 61 let mut unit_attr_table = HashMap::new(); 62 unit_attr_table.insert("WantedBy", InstallUnitAttr::WantedBy); 63 unit_attr_table.insert("RequiredBy", InstallUnitAttr::RequiredBy); 64 unit_attr_table.insert("Also", InstallUnitAttr::Also); 65 unit_attr_table.insert("Alias", InstallUnitAttr::Alias); 66 unit_attr_table 67 }; 68 pub static ref SERVICE_UNIT_ATTR_TABLE: HashMap<&'static str, ServiceUnitAttr> = { 69 let mut unit_attr_table = HashMap::new(); 70 unit_attr_table.insert("Type", ServiceUnitAttr::Type); 71 unit_attr_table.insert("RemainAfterExit", ServiceUnitAttr::RemainAfterExit); 72 unit_attr_table.insert("ExecStart", ServiceUnitAttr::ExecStart); 73 unit_attr_table.insert("ExecStartPre", ServiceUnitAttr::ExecStartPre); 74 unit_attr_table.insert("ExecStartPos", ServiceUnitAttr::ExecStartPos); 75 unit_attr_table.insert("ExecReload", ServiceUnitAttr::ExecReload); 76 unit_attr_table.insert("ExecStop", ServiceUnitAttr::ExecStop); 77 unit_attr_table.insert("ExecStopPost", ServiceUnitAttr::ExecStopPost); 78 unit_attr_table.insert("RestartSec", ServiceUnitAttr::RestartSec); 79 unit_attr_table.insert("Restart", ServiceUnitAttr::Restart); 80 unit_attr_table.insert("TimeoutStartSec", ServiceUnitAttr::TimeoutStartSec); 81 unit_attr_table.insert("TimeoutStopSec", ServiceUnitAttr::TimeoutStopSec); 82 unit_attr_table.insert("Environment", ServiceUnitAttr::Environment); 83 unit_attr_table.insert("EnvironmentFile", ServiceUnitAttr::EnvironmentFile); 84 unit_attr_table.insert("Nice", ServiceUnitAttr::Nice); 85 unit_attr_table.insert("WorkingDirectory", ServiceUnitAttr::WorkingDirectory); 86 unit_attr_table.insert("RootDirectory", ServiceUnitAttr::RootDirectory); 87 unit_attr_table.insert("User", ServiceUnitAttr::User); 88 unit_attr_table.insert("Group", ServiceUnitAttr::Group); 89 unit_attr_table.insert("MountFlags", ServiceUnitAttr::MountFlags); 90 unit_attr_table 91 }; 92 pub static ref BASE_UNIT_ATTR_TABLE: HashMap<&'static str, BaseUnitAttr> = { 93 let mut unit_attr_table = HashMap::new(); 94 unit_attr_table.insert("Description", BaseUnitAttr::Description); 95 unit_attr_table.insert("Documentation", BaseUnitAttr::Documentation); 96 unit_attr_table.insert("Requires", BaseUnitAttr::Requires); 97 unit_attr_table.insert("Wants", BaseUnitAttr::Wants); 98 unit_attr_table.insert("After", BaseUnitAttr::After); 99 unit_attr_table.insert("Before", BaseUnitAttr::Before); 100 unit_attr_table.insert("Binds To", BaseUnitAttr::BindsTo); 101 unit_attr_table.insert("Part Of", BaseUnitAttr::PartOf); 102 unit_attr_table.insert("OnFailure", BaseUnitAttr::OnFailure); 103 unit_attr_table.insert("Conflicts", BaseUnitAttr::Conflicts); 104 unit_attr_table 105 }; 106 pub static ref BASE_IEC: HashMap<&'static str, u64> = { 107 let mut table = HashMap::new(); 108 table.insert( 109 "E", 110 1024u64 * 1024u64 * 1024u64 * 1024u64 * 1024u64 * 1024u64, 111 ); 112 table.insert("P", 1024u64 * 1024u64 * 1024u64 * 1024u64 * 1024u64); 113 table.insert("T", 1024u64 * 1024u64 * 1024u64 * 1024u64); 114 table.insert("G", 1024u64 * 1024u64 * 1024u64); 115 table.insert("M", 1024u64 * 1024u64); 116 table.insert("K", 1024u64); 117 table.insert("B", 1u64); 118 table.insert("", 1u64); 119 table 120 }; 121 pub static ref BASE_SI: HashMap<&'static str, u64> = { 122 let mut table = HashMap::new(); 123 table.insert( 124 "E", 125 1000u64 * 1000u64 * 1000u64 * 1000u64 * 1000u64 * 1000u64, 126 ); 127 table.insert("P", 1000u64 * 1000u64 * 1000u64 * 1000u64 * 1000u64); 128 table.insert("T", 1000u64 * 1000u64 * 1000u64 * 1000u64); 129 table.insert("G", 1000u64 * 1000u64 * 1000u64); 130 table.insert("M", 1000u64 * 1000u64); 131 table.insert("K", 1000u64); 132 table.insert("B", 1u64); 133 table.insert("", 1u64); 134 table 135 }; 136 pub static ref SEC_UNIT_TABLE: HashMap<&'static str, u64> = { 137 let mut table = HashMap::new(); 138 table.insert("h", 60 * 60 * 1000 * 1000 * 1000); 139 table.insert("min", 60 * 1000 * 1000 * 1000); 140 table.insert("m", 60 * 1000 * 1000 * 1000); 141 table.insert("s", 1000 * 1000 * 1000); 142 table.insert("", 1000 * 1000 * 1000); 143 table.insert("ms", 1000 * 1000); 144 table.insert("us", 1000); 145 table.insert("ns", 1); 146 table 147 }; 148 pub static ref TIMER_UNIT_ATTR_TABLE: HashMap<&'static str, TimerUnitAttr> = { 149 let mut map = HashMap::new(); 150 map.insert("OnActiveSec", TimerUnitAttr::OnActiveSec); 151 map.insert("OnBootSec", TimerUnitAttr::OnBootSec); 152 map.insert("OnStartupSec", TimerUnitAttr::OnStartUpSec); 153 map.insert("OnUnitActiveSec", TimerUnitAttr::OnUnitInactiveSec); 154 map.insert("OnUnitInactiveSec", TimerUnitAttr::OnUnitInactiveSec); 155 map.insert("OnCalendar", TimerUnitAttr::OnCalendar); 156 map.insert("AccuracySec", TimerUnitAttr::AccuarcySec); 157 map.insert("RandomizedDelaySec", TimerUnitAttr::RandomizedDelaySec); 158 map.insert("FixedRandomDelay", TimerUnitAttr::FixedRandomDelay); 159 map.insert("OnClockChange", TimerUnitAttr::OnClockChange); 160 map.insert("OnTimezoneChange", TimerUnitAttr::OnTimeZoneChange); 161 map.insert("Unit", TimerUnitAttr::Unit); 162 map.insert("Persistent", TimerUnitAttr::Persistent); 163 map.insert("WakeSystem", TimerUnitAttr::WakeSystem); 164 map.insert("RemainAfterElapse", TimerUnitAttr::RemainAfterElapse); 165 map 166 }; 167 } 168 169 //用于解析Unit共有段的方法 170 pub struct UnitParser; 171 172 impl UnitParser { 173 /// @brief 从path获取到BufReader,此方法将会检验文件类型 174 /// 175 /// 如果指定UnitType,则进行文件名检查 176 /// 177 /// @param path 需解析的文件路径 178 /// 179 /// @param unit_type 指定Unit类型 180 /// 181 /// @return 成功则返回对应BufReader,否则返回Err 182 pub fn get_reader(path: &str, unit_type: UnitType) -> Result<io::BufReader<File>, ParseError> { 183 //判断是否为路径,若不为路径则到定向到默认unit文件夹 184 let mut realpath = path.to_string(); 185 if !path.contains('/') { 186 realpath = format!("{}{}", DRAGON_REACH_UNIT_DIR, &path).to_string(); 187 } 188 let path = realpath.as_str(); 189 // 如果指定UnitType,则进行文件名检查,不然直接返回reader 190 if unit_type != UnitType::Unknown { 191 let suffix = match path.rfind('.') { 192 Some(idx) => &path[idx + 1..], 193 None => { 194 return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)); 195 } 196 }; 197 let u_type = UNIT_SUFFIX.get(suffix); 198 if u_type.is_none() { 199 return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)); 200 } 201 if *(u_type.unwrap()) != unit_type { 202 return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)); 203 } 204 } 205 let file = match File::open(path) { 206 Ok(file) => file, 207 Err(_) => { 208 return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)); 209 } 210 }; 211 return Ok(io::BufReader::new(file)); 212 } 213 214 pub fn from_path(path: &str) -> Result<usize, ParseError> { 215 let unit_type = UnitParseUtil::parse_type(&path); 216 match unit_type { 217 UnitType::Service => ServiceParser::parse(path), 218 UnitType::Target => TargetParser::parse(path), 219 _ => Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)), 220 } 221 } 222 223 /// @brief 将path路径的文件解析为unit_type类型的Unit 224 /// 225 /// 该方法解析每个Unit共有的段(Unit,Install),其余独有的段属性将会交付T类型的Unit去解析 226 /// 227 /// @param path 需解析的文件路径 228 /// 229 /// @param unit_type 指定Unit类型 230 /// 231 /// @return 解析成功则返回Ok(Arc<T>),否则返回Err 232 pub fn parse<T: Unit + Default + Clone + 'static>( 233 path: &str, 234 unit_type: UnitType, 235 ) -> Result<usize, ParseError> { 236 let name = match path.rfind("/") { 237 Some(size) => String::from(&path[size..]), 238 None => String::from(path), 239 }; 240 // 如果该文件已解析过,则直接返回id 241 if UnitManager::contains_name(&name) { 242 let unit = UnitManager::get_unit_with_name(&name).unwrap(); 243 let unit = unit.lock().unwrap(); 244 return Ok(unit.unit_id()); 245 } 246 247 let mut unit: T = T::default(); 248 let mut unit_base = BaseUnit::default(); 249 //设置unit类型标记 250 unit_base.set_unit_type(unit_type); 251 252 let reader = UnitParser::get_reader(path, unit_type)?; 253 254 //用于记录当前段的类型 255 let mut segment = Segment::None; 256 //用于处理多行对应一个属性的情况 257 let _last_attr = ServiceUnitAttr::None; 258 259 //一行一行向下解析 260 let lines = reader 261 .lines() 262 .map(|line| line.unwrap()) 263 .collect::<Vec<String>>(); 264 let mut i = 0; 265 while i < lines.len() { 266 let line = &lines[i]; 267 //空行跳过 268 if line.chars().all(char::is_whitespace) { 269 i += 1; 270 continue; 271 } 272 //注释跳过 273 if line.starts_with('#') { 274 i += 1; 275 continue; 276 } 277 let mut line = line.trim(); 278 let segment_flag = SEGMENT_TABLE.get(&line); 279 if !segment_flag.is_none() { 280 //如果当前行匹配到的为段名,则切换段类型继续匹配下一行 281 segment = *segment_flag.unwrap(); 282 i += 1; 283 continue; 284 } 285 if segment == Segment::None { 286 //未找到段名则不能继续匹配 287 return Err(ParseError::new( 288 ParseErrorType::ESyntaxError, 289 path.to_string(), 290 i + 1, 291 )); 292 } 293 294 //下面进行属性匹配 295 //合并多行为一个属性的情况 296 //最后一个字符为\,代表换行,将多行转换为一行统一解析 297 let mut templine = String::new(); 298 if lines[i].ends_with('\\') { 299 while lines[i].ends_with('\\') { 300 let temp = &lines[i][..lines[i].len() - 1]; 301 templine = format!("{} {}", templine, temp); 302 i += 1; 303 } 304 templine = format!("{} {}", templine, lines[i]); 305 line = templine.as_str(); 306 i += 1; 307 } 308 //=号分割后第一个元素为属性,后面的均为值 309 let (attr_str, val_str) = match line.find('=') { 310 Some(idx) => (line[..idx].trim(), line[idx + 1..].trim()), 311 None => { 312 return Err(ParseError::new( 313 ParseErrorType::ESyntaxError, 314 path.to_string(), 315 i + 1, 316 )); 317 } 318 }; 319 //首先匹配所有unit文件都有的unit段和install段 320 if BASE_UNIT_ATTR_TABLE.get(attr_str).is_some() { 321 if segment != Segment::Unit { 322 return Err(ParseError::new( 323 ParseErrorType::EINVAL, 324 path.to_string(), 325 i + 1, 326 )); 327 } 328 if let Err(e) = unit_base 329 .set_unit_part_attr(BASE_UNIT_ATTR_TABLE.get(attr_str).unwrap(), val_str) 330 { 331 let mut e = e.clone(); 332 e.set_file(path); 333 e.set_linenum(i + 1); 334 return Err(e); 335 } 336 } else if INSTALL_UNIT_ATTR_TABLE.get(attr_str).is_some() { 337 if segment != Segment::Install { 338 return Err(ParseError::new( 339 ParseErrorType::EINVAL, 340 path.to_string(), 341 i + 1, 342 )); 343 } 344 if let Err(e) = unit_base 345 .set_install_part_attr(INSTALL_UNIT_ATTR_TABLE.get(attr_str).unwrap(), val_str) 346 { 347 let mut e = e.clone(); 348 e.set_file(path); 349 e.set_linenum(i + 1); 350 return Err(e); 351 } 352 } else { 353 if let Err(e) = unit.set_attr(segment, attr_str, val_str) { 354 let mut e = e.clone(); 355 e.set_file(path); 356 e.set_linenum(i + 1); 357 return Err(e); 358 } 359 } 360 i += 1; 361 } 362 363 unit.set_unit_base(unit_base); 364 unit.set_unit_name(name.clone()); 365 let id = unit.set_unit_id(); 366 unit.init(); 367 let dret: Arc<Mutex<dyn Unit>> = Arc::new(Mutex::new(unit)); 368 UnitManager::insert_unit_with_id(id, dret); 369 UnitManager::insert_into_name_table(&name, id); 370 371 return Ok(id); 372 } 373 } 374