mod.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. use crate::{
  2. contants::{AF_INET, AF_INET6, IPV4_MIN_MTU, IPV6_MIN_MTU, PRIO_MAX, PRIO_MIN},
  3. error::{ParseError, ParseErrorType},
  4. task::cmdtask::CmdTask,
  5. unit::{Unit, Url},
  6. FileDescriptor,
  7. };
  8. #[cfg(target_os = "dragonos")]
  9. use drstd as std;
  10. use std::{
  11. format, fs, path::Path, print, println, rc::Rc, string::String, string::ToString, vec, vec::Vec, os::unix::prelude::PermissionsExt,
  12. };
  13. use std::os::unix::fs::MetadataExt;
  14. use super::{
  15. parse_service::ServiceParser, parse_target::TargetParser, BASE_IEC, BASE_SI, SEC_UNIT_TABLE,
  16. };
  17. #[derive(PartialEq)]
  18. pub enum SizeBase {
  19. IEC,
  20. Si,
  21. }
  22. pub struct UnitParseUtil;
  23. impl UnitParseUtil {
  24. /// @brief 解析布尔值
  25. ///
  26. /// 将传入的字符串解析为布尔值
  27. /// "yes","y","1","true","t","on"均可表示true
  28. /// "no","n","0","false","f","off"均可表示false
  29. ///
  30. /// @param s 需解析的字符串
  31. ///
  32. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  33. pub fn parse_boolean(s: &str) -> Result<bool, ParseError> {
  34. let t_table: Vec<&str> = vec!["yes", "y", "1", "true", "t", "on"];
  35. let f_table: Vec<&str> = vec!["no", "n", "0", "false", "f", "off"];
  36. if t_table.contains(&s) {
  37. return Ok(true);
  38. } else if f_table.contains(&s) {
  39. return Ok(false);
  40. }
  41. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  42. }
  43. /// @brief 解析pid
  44. ///
  45. /// 将传入的字符串解析为pid
  46. ///
  47. /// @param s 需解析的字符串
  48. ///
  49. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  50. pub fn parse_pid(s: &str) -> Result<i32, ParseError> {
  51. let s = s.trim();
  52. //先使用u64变换
  53. let pid_ul = match s.parse::<u64>() {
  54. Ok(val) => val,
  55. Err(_) => {
  56. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  57. }
  58. };
  59. let pid: i32 = pid_ul as i32;
  60. if (pid as u64) != pid_ul {
  61. //如果在从pid_t转换为u64之后与之前不等,则说明发生了截断,返回错误
  62. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  63. }
  64. if pid < 0 {
  65. //pid小于0不合法
  66. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  67. }
  68. return Ok(pid);
  69. }
  70. /// @brief 解析pid
  71. ///
  72. /// 将传入的字符串解析为mode_t
  73. ///
  74. /// @param s 需解析的字符串
  75. ///
  76. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  77. pub fn parse_mode(s: &str) -> Result<u32, ParseError> {
  78. let s = s.trim();
  79. let m = match u32::from_str_radix(s, 8) {
  80. Ok(val) => val,
  81. Err(_) => {
  82. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  83. }
  84. };
  85. //如果模式大于权限的最大值则为非法权限,返回错误
  86. if m > 0o7777 {
  87. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  88. }
  89. return Ok(m);
  90. }
  91. /// @brief 解析网络接口索引
  92. ///
  93. /// 将传入的字符串解析为网络接口索引具体值
  94. ///
  95. /// @param s 需解析的字符串
  96. ///
  97. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  98. pub fn parse_ifindex(s: &str) -> Result<i32, ParseError> {
  99. let s = s.trim();
  100. let ret: i32 = match s.parse::<i32>() {
  101. Ok(val) => val,
  102. Err(_) => {
  103. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  104. }
  105. };
  106. if ret <= 0 {
  107. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  108. }
  109. return Ok(ret);
  110. }
  111. /// @brief 解析最大传输单元(MTU)
  112. ///
  113. /// 将传入的字符串解析为具体值
  114. ///
  115. /// @param s 需解析的字符串
  116. ///
  117. /// @param family 网络地址族
  118. ///
  119. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  120. pub fn parse_mtu(s: &str, family: i32) -> Result<u32, ParseError> {
  121. let s = s.trim();
  122. let mtu = match s.parse::<u64>() {
  123. Ok(val) => val,
  124. Err(_) => {
  125. //针对非法字符出错时
  126. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  127. }
  128. };
  129. //针对数据溢出时的报错
  130. if mtu > u32::MAX as u64 {
  131. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  132. }
  133. let mtu: u32 = mtu as u32;
  134. let mut min_mtu: u32 = 0;
  135. //判断mtu是否合法
  136. if family == AF_INET6 {
  137. min_mtu = IPV6_MIN_MTU;
  138. } else if family == AF_INET {
  139. min_mtu = IPV4_MIN_MTU;
  140. } else {
  141. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  142. }
  143. return Ok(mtu);
  144. }
  145. /// @brief 解析Size
  146. ///
  147. /// 将传入的字符串解析为具体的字节数
  148. /// 可支持IEC二进制后缀,也可支持SI十进制后缀
  149. ///
  150. /// @param s 需解析的字符串
  151. ///
  152. /// @param base 设置为IEC二进制后缀或者SI十进制后缀
  153. ///
  154. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  155. pub fn parse_size(s: &str, base: SizeBase) -> Result<u64, ParseError> {
  156. let s = s.trim();
  157. //将s分解为数字和后缀部分
  158. let (number_str, suffix) = match s.find(|c: char| !c.is_digit(10) && c != '.') {
  159. Some(mid) => s.split_at(mid),
  160. None => (s, ""),
  161. };
  162. //获得数字部分的整数和小数部分
  163. let (integer, fraction) = match number_str.find(".") {
  164. Some(mid) => {
  165. let (integer, fraction) = number_str.split_at(mid);
  166. let integer = integer.parse::<u64>().unwrap();
  167. let fraction = match fraction[1..].parse::<u64>() {
  168. Ok(val) => val,
  169. Err(_) => {
  170. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  171. }
  172. };
  173. (integer, fraction)
  174. }
  175. None => (number_str.parse::<u64>().unwrap(), 0),
  176. };
  177. //从表中查找到后缀所对应的字节倍数
  178. let mut factor: u64 = 0;
  179. if base == SizeBase::IEC {
  180. factor = match BASE_IEC.get(suffix) {
  181. Some(val) => *val,
  182. None => {
  183. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  184. }
  185. }
  186. } else if base == SizeBase::Si {
  187. factor = match BASE_SI.get(suffix) {
  188. Some(val) => *val,
  189. None => {
  190. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  191. }
  192. }
  193. }
  194. Ok(integer * factor + (fraction * factor) / (10u64.pow(fraction.to_string().len() as u32)))
  195. }
  196. /// @brief 解析扇区大小
  197. ///
  198. /// 将传入的字符串解析为具体的扇区大小
  199. /// 若扇区大小小于512或者大于4096,将会返回错误,若扇区大小不为2的幂,返回错误。
  200. ///
  201. /// @param s 需解析的字符串
  202. ///
  203. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  204. pub fn parse_sector_size(s: &str) -> Result<u64, ParseError> {
  205. let s = s.trim();
  206. let size: u64 = match s.parse::<u64>() {
  207. Ok(val) => val,
  208. Err(_) => {
  209. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  210. }
  211. };
  212. if size < 512 || size > 4096 {
  213. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  214. }
  215. //判断是否为2的幂,如果不是则报错
  216. if (size & (size - 1)) != 0 {
  217. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  218. }
  219. return Ok(size);
  220. }
  221. /// @brief 解析范围
  222. ///
  223. /// 将传入的字符串解析为具体的范围
  224. ///
  225. /// @param s 需解析的字符串
  226. ///
  227. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  228. pub fn parse_range(s: &str) -> Result<(u32, u32), ParseError> {
  229. let mid = match s.find('-') {
  230. Some(val) => val,
  231. None => {
  232. //如果字符串中没有'-'符号,则表示一个值,所以范围两端都为该值
  233. let s = s.trim();
  234. let ret = match s.parse::<u32>() {
  235. Ok(val) => val,
  236. Err(_) => {
  237. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  238. }
  239. };
  240. return Ok((ret, ret));
  241. }
  242. };
  243. //若字符串中存在'-',则分别解析为u32,解析失败则报错
  244. let (l, r) = s.split_at(mid);
  245. let l = l.trim();
  246. let l = match l.parse::<u32>() {
  247. Ok(val) => val,
  248. Err(_) => {
  249. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  250. }
  251. };
  252. let r = r.trim();
  253. let r = match r.parse::<u32>() {
  254. Ok(val) => val,
  255. Err(_) => {
  256. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  257. }
  258. };
  259. return Ok((l, r));
  260. }
  261. /// @brief 解析文件描述符
  262. ///
  263. /// 将传入的字符串解析为文件描述符fd
  264. ///
  265. /// @param s 需解析的字符串
  266. ///
  267. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  268. pub fn parse_fd(s: &str) -> Result<FileDescriptor, ParseError> {
  269. let s = s.trim();
  270. let fd = match s.parse::<i32>() {
  271. Ok(val) => val,
  272. Err(_) => {
  273. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  274. }
  275. };
  276. if fd < 0 {
  277. return Err(ParseError::new(ParseErrorType::EBADF, String::new(), 0));
  278. }
  279. return Ok(FileDescriptor(fd as usize));
  280. }
  281. /// @brief 解析nice
  282. ///
  283. /// 将传入的字符串解析为nice
  284. ///
  285. /// @param s 需解析的字符串
  286. ///
  287. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  288. pub fn parse_nice(s: &str) -> Result<i8, ParseError> {
  289. let s = s.trim();
  290. let nice = match s.parse::<i8>() {
  291. Ok(val) => val,
  292. Err(_) => {
  293. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  294. }
  295. };
  296. if nice > PRIO_MAX || nice < PRIO_MIN {
  297. return Err(ParseError::new(ParseErrorType::ERANGE, String::new(), 0));
  298. }
  299. return Ok(nice);
  300. }
  301. /// @brief 解析端口号
  302. ///
  303. /// 将传入的字符串解析为端口号
  304. ///
  305. /// @param s 需解析的字符串
  306. ///
  307. /// @return 解析成功则返回Ok(解析后的值),否则返回Err
  308. pub fn parse_ip_port(s: &str) -> Result<u16, ParseError> {
  309. let s = s.trim();
  310. let port = match s.parse::<u16>() {
  311. Ok(val) => val,
  312. Err(_) => {
  313. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  314. }
  315. };
  316. if port == 0 {
  317. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  318. }
  319. return Ok(port);
  320. }
  321. /// @brief 解析端口范围
  322. ///
  323. /// 将传入的字符串解析为端口范围
  324. ///
  325. /// @param s 需解析的字符串
  326. ///
  327. /// @return 解析成功则返回Ok((u16,u16)),否则返回Err
  328. pub fn parse_ip_port_range(s: &str) -> Result<(u16, u16), ParseError> {
  329. let (l, h) = Self::parse_range(s)?;
  330. let l = l as u16;
  331. let h = h as u16;
  332. if l <= 0 || l >= 65535 || h <= 0 || h >= 65535 {
  333. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  334. }
  335. return Ok((l, h));
  336. }
  337. /// @brief 解析OOM(Out-of-Memory)分数调整值
  338. ///
  339. /// 将传入的字符串解析为OOM(Out-of-Memory)分数调整值
  340. ///
  341. /// @param s 需解析的字符串
  342. ///
  343. /// @return 解析成功则返回Ok(u32),否则返回Err
  344. pub fn parse_ip_prefix_length(s: &str) -> Result<u32, ParseError> {
  345. let len = match s.parse::<u32>() {
  346. Ok(val) => val,
  347. Err(_) => {
  348. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  349. }
  350. };
  351. if len > 128 {
  352. return Err(ParseError::new(ParseErrorType::ERANGE, String::new(), 0));
  353. }
  354. return Ok(len);
  355. }
  356. /// @brief 目前为简单的分割字符串,并未提供严谨的Url解析
  357. ///
  358. /// 将传入的字符串解析为Url结构体的Vec,若Url非法则返回错误
  359. ///
  360. /// @param s 需解析的字符串
  361. ///
  362. /// @return 解析成功则返回Ok(Url),否则返回Err
  363. pub fn parse_url(s: &str) -> Result<Vec<Url>, ParseError> {
  364. let mut url = Url::default();
  365. let url_strs = s.split_whitespace().collect::<Vec<&str>>();
  366. let mut urls = Vec::new();
  367. for s in url_strs {
  368. urls.push(Url {
  369. url_string: String::from(s),
  370. })
  371. }
  372. return Ok(urls);
  373. }
  374. /// @brief 将对应的str解析为对应Unit
  375. ///
  376. /// 将传入的字符串解析为Unit,解析失败返回错误
  377. ///
  378. /// @param path 需解析的文件
  379. ///
  380. /// @return 解析成功则返回Ok(Rc<dyn Unit>),否则返回Err
  381. pub fn parse_unit<T: Unit>(path: &str) -> Result<Rc<T>, ParseError> {
  382. return T::from_path(path);
  383. }
  384. /// @brief 将对应的str解析为Rc<dyn Unit>
  385. ///
  386. /// 将传入的字符串解析为Rc<dyn Unit>,解析失败返回错误
  387. ///
  388. /// @param path 需解析的文件
  389. ///
  390. /// @return 解析成功则返回Ok(Rc<dyn Unit>),否则返回Err
  391. pub fn parse_unit_no_type(path: &str) -> Result<Rc<dyn Unit>, ParseError> {
  392. let idx = match path.rfind('.') {
  393. Some(val) => val,
  394. None => {
  395. return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0));
  396. }
  397. };
  398. if idx == path.len() - 1 {
  399. //处理非法文件xxxx. 类型
  400. return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0));
  401. }
  402. let suffix = &path[idx + 1..];
  403. //通过文件后缀分发给不同类型的Unit解析器解析
  404. let unit: Rc<dyn Unit> = match suffix {
  405. //TODO: 目前为递归,后续应考虑从DragonReach管理的Unit表中寻找是否有该Unit,并且通过记录消除递归
  406. "service" => ServiceParser::parse(path)?,
  407. "target" => TargetParser::parse(path)?,
  408. _ => {
  409. return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0));
  410. }
  411. };
  412. return Ok(unit);
  413. }
  414. /// @brief 将对应的str解析为对应CmdTask
  415. ///
  416. /// 将传入的字符串解析为CmdTask组,解析失败返回错误
  417. ///
  418. /// @param path 需解析的文件
  419. ///
  420. /// @return 解析成功则返回Ok(Vec<CmdTask>>),否则返回Err
  421. pub fn parse_cmd_task(s: &str) -> Result<Vec<CmdTask>, ParseError> {
  422. //分拆成单词Vec
  423. let cmds = s.split_whitespace().collect::<Vec<&str>>();
  424. let mut tasks = Vec::new();
  425. let mut i = 0;
  426. while i < cmds.len() {
  427. let mut cmd_task = CmdTask {
  428. path: String::new(),
  429. cmd: String::new(),
  430. ignore: false,
  431. };
  432. //匹配到这里时,这个单词肯定是路径,若路径以-开头则设置ignore
  433. cmd_task.ignore = cmds[i].starts_with('-');
  434. //获取到一个CmdTask的路径部分
  435. let mut path = "";
  436. if cmd_task.ignore {
  437. path = &cmds[i][1..];
  438. } else {
  439. path = &cmds[i];
  440. }
  441. //得到的非绝对路径则不符合语法要求,报错
  442. if !UnitParseUtil::is_valid_exec_path(path) {
  443. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  444. }
  445. cmd_task.path = String::from(path);
  446. //i += 1,继续匹配下一个单词
  447. i += 1;
  448. let mut cmd_str = String::new();
  449. while i < cmds.len() && !UnitParseUtil::is_valid_exec_path(cmds[i]) {
  450. //命令可能会有多个单词,将多个命令整理成一个
  451. let cmd = cmds[i];
  452. cmd_str = format!("{} {}", cmd_str, cmd);
  453. i += 1;
  454. }
  455. cmd_task.cmd = cmd_str;
  456. tasks.push(cmd_task);
  457. //经过while到这里之后,cmds[i]对应的单词一点是路径,i不需要加一
  458. }
  459. return Ok(tasks);
  460. }
  461. /// @brief 判断是否为绝对路径,以及指向是否为可执行文件或者sh脚本
  462. ///
  463. /// 目前该方法仅判断是否为绝对路径
  464. ///
  465. /// @param path 路径
  466. ///
  467. /// @return 解析成功则返回true,否则返回false
  468. pub fn is_valid_exec_path(path: &str) -> bool {
  469. if !path.starts_with("/"){
  470. return false;
  471. }
  472. return true;
  473. //TODO: 后续应判断该文件是否为合法文件
  474. //let path = Path::new(path);
  475. //return Self::is_executable_file(path) || Self::is_shell_script(path);
  476. }
  477. pub fn is_valid_file(path: &str) -> bool {
  478. if !path.starts_with("/"){
  479. return false;
  480. }
  481. let path = Path::new(path);
  482. if let Ok(matadata) = fs::metadata(path) {
  483. return matadata.is_file();
  484. }
  485. return false;
  486. }
  487. fn is_executable_file(path: &Path) -> bool {
  488. if let Ok(metadata) = fs::metadata(path) {
  489. // 检查文件类型是否是普通文件并且具有可执行权限
  490. if metadata.is_file(){
  491. let permissions = metadata.permissions().mode();
  492. return permissions & 0o111 != 0;
  493. }
  494. }
  495. false
  496. }
  497. fn is_shell_script(path: &Path) -> bool {
  498. if let Some(extension) = path.extension() {
  499. if extension == "sh" {
  500. return true;
  501. }
  502. }
  503. false
  504. }
  505. /// @brief 将对应的str解析为us(微秒)
  506. ///
  507. /// 将传入的字符串解析为秒数,解析失败返回错误
  508. ///
  509. /// @param path 需解析的文件
  510. ///
  511. /// @return 解析成功则返回Ok(u64),否则返回Err
  512. pub fn parse_sec(s: &str) -> Result<u64, ParseError> {
  513. //下列参数分别记录整数部分,小数部分以及单位
  514. let mut integer: u64 = 0;
  515. let mut frac: u64 = 0;
  516. let mut unit: &str = "";
  517. match s.find('.') {
  518. Some(idx) => {
  519. //解析整数部分
  520. integer = match s[..idx].parse::<u64>() {
  521. Ok(val) => val,
  522. Err(_) => {
  523. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0))
  524. }
  525. };
  526. //获得小数+单位的字符串
  527. let frac_and_unit = &s[(idx + 1)..];
  528. match frac_and_unit.find(|c: char| !c.is_digit(10)) {
  529. Some(val) => {
  530. //匹配小数部分
  531. frac = match frac_and_unit[..val].parse::<u64>() {
  532. Ok(val) => val,
  533. Err(_) => {
  534. return Err(ParseError::new(
  535. ParseErrorType::EINVAL,
  536. String::new(),
  537. 0,
  538. ))
  539. }
  540. };
  541. //单位部分
  542. unit = &frac_and_unit[val..];
  543. }
  544. None => {
  545. //没有单位的情况,直接匹配小数
  546. frac = match frac_and_unit.parse::<u64>() {
  547. Ok(val) => val,
  548. Err(_) => {
  549. return Err(ParseError::new(
  550. ParseErrorType::EINVAL,
  551. String::new(),
  552. 0,
  553. ))
  554. }
  555. };
  556. unit = "";
  557. }
  558. };
  559. }
  560. None => {
  561. //没有小数点则直接匹配整数部分和单位部分
  562. match s.find(|c: char| !c.is_digit(10)) {
  563. Some(idx) => {
  564. integer = match s[..idx].parse::<u64>() {
  565. Ok(val) => val,
  566. Err(_) => {
  567. return Err(ParseError::new(
  568. ParseErrorType::EINVAL,
  569. String::new(),
  570. 0,
  571. ))
  572. }
  573. };
  574. unit = &s[idx..];
  575. }
  576. None => {
  577. integer = match s.parse::<u64>() {
  578. Ok(val) => val,
  579. Err(_) => {
  580. return Err(ParseError::new(
  581. ParseErrorType::EINVAL,
  582. String::new(),
  583. 0,
  584. ))
  585. }
  586. };
  587. unit = "";
  588. }
  589. };
  590. }
  591. };
  592. //从时间单位转换表中获取到单位转换为ns的倍数
  593. let factor = match SEC_UNIT_TABLE.get(unit) {
  594. Some(val) => val,
  595. None => {
  596. return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
  597. }
  598. };
  599. //计算ns
  600. return Ok(integer * factor + (frac * factor) / (10u64.pow(frac.to_string().len() as u32)));
  601. }
  602. /// @brief 判断对应路径是否为目录
  603. ///
  604. /// @param path 路径
  605. ///
  606. /// @return true/false
  607. pub fn is_dir(path: &str) -> bool {
  608. if let Ok(metadata) = fs::metadata(path) {
  609. if metadata.is_dir() {
  610. return true;
  611. }
  612. return false;
  613. }
  614. return false;
  615. }
  616. }