utils.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*************************************************************************
  2. *
  3. * Copyright (C) 2018-2025 Ruilin Peng (Nick) <[email protected]>.
  4. *
  5. * smartdns is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * smartdns is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. use nix::libc;
  19. use pbkdf2::{
  20. password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
  21. Pbkdf2,
  22. };
  23. pub fn parse_value<T>(value: Option<String>, min: T, max: T, default: T) -> T
  24. where
  25. T: PartialOrd + std::str::FromStr,
  26. {
  27. if value.is_none() {
  28. return default;
  29. }
  30. let value = value.unwrap().parse::<T>();
  31. if let Err(_) = value {
  32. return default;
  33. }
  34. let mut value = value.unwrap_or_else(|_| default);
  35. if value < min {
  36. value = min;
  37. }
  38. if value > max {
  39. value = max;
  40. }
  41. value
  42. }
  43. pub fn seconds_until_next_hour() -> u64 {
  44. let now = chrono::Local::now();
  45. let minutes = chrono::Timelike::minute(&now);
  46. let seconds = chrono::Timelike::second(&now);
  47. let remaining_seconds = 3600 - (minutes * 60 + seconds) as u64;
  48. remaining_seconds
  49. }
  50. pub fn get_free_disk_space(path: &str) -> u64 {
  51. let path = std::ffi::CString::new(path).unwrap();
  52. let mut statvfs: libc::statvfs = unsafe { std::mem::zeroed() };
  53. let ret = unsafe { libc::statvfs(path.as_ptr(), &mut statvfs) };
  54. if ret != 0 {
  55. return 0;
  56. }
  57. statvfs.f_bsize as u64 * statvfs.f_bavail as u64
  58. }
  59. pub fn hash_password(password: &str, round: Option<u32>) -> Result<String, Box<dyn std::error::Error>> {
  60. let salt = SaltString::generate(&mut OsRng);
  61. let mut parm = pbkdf2::Params::default();
  62. parm.rounds = round.unwrap_or(10000);
  63. let password_hash = Pbkdf2
  64. .hash_password_customized(password.as_bytes(), None, None, parm, &salt)
  65. .map_err(|e| e.to_string())?
  66. .to_string();
  67. Ok(password_hash)
  68. }
  69. pub fn verify_password(password: &str, password_hash: &str) -> bool {
  70. let parsed_hash = match PasswordHash::new(&password_hash) {
  71. Ok(h) => h,
  72. Err(_) => return false,
  73. };
  74. Pbkdf2
  75. .verify_password(password.as_bytes(), &parsed_hash)
  76. .is_ok()
  77. }
  78. pub fn get_page_size() -> usize {
  79. // Use libc to get the system page size
  80. unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
  81. }