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