1use crate::bad_action::BadAction;
2use crate::distribution::{check_distribution};
3use regex::Regex;
4use std::env::current_dir;
5use std::fs::File;
6use std::io::{BufRead, BufReader};
7use std::path::{Path, PathBuf};
8use walkdir::WalkDir;
9
10mod bad_action;
11mod distribution;
12mod file_attr;
13mod packages;
14mod release;
15
16pub mod log_config;
17
18pub fn check_repository(repository_dir: &Path, delete: bool) {
19 log::info!(repository_dir:?, delete; "start checking repository");
20
21 let bad_action = BadAction::new(delete);
22
23 let dists_dir = repository_dir.join("dists");
24 let pool_dir = repository_dir.join("pool");
25 if dists_dir.is_dir() && pool_dir.is_dir() {
26 if let Ok(reader) = dists_dir.read_dir() {
28 for entry in reader {
29 if let Ok(entry) = entry
30 && let Ok(file_type) = entry.file_type()
31 && file_type.is_dir()
32 && !file_type.is_symlink()
33 {
34 check_distribution(repository_dir, &entry.path(), &bad_action);
35 }
36 }
37 }
38 } else {
39 check_distribution(repository_dir, repository_dir, &bad_action);
41 }
42}
43
44fn check_site(site_dir: &Path, delete: bool) {
45 log::info!(site_dir:?, delete; "start checking site");
46
47 WalkDir::new(site_dir)
53 .into_iter()
54 .filter_map(|entry| entry.ok())
55 .filter(|entry| entry.file_type().is_dir() && entry.file_name().to_str() == Some("dists"))
56 .filter_map(|entry| entry.path().parent().map(|p| p.to_path_buf()))
57 .for_each(|repository_dir| {
58 check_repository(&repository_dir, delete);
59 });
60}
61
62pub fn check_mirror<P>(base_dir: P, delete: bool)
68where
69 P: AsRef<Path>,
70{
71 let base_dir = base_dir.as_ref();
72 let mirror_dir = base_dir.join("mirror");
73
74 log::info!(base_dir:?, delete; "start checking mirror");
75
76 match mirror_dir.read_dir() {
77 Ok(reader) => {
78 for entry in reader {
79 if let Ok(entry) = entry
80 && let Ok(file_type) = entry.file_type()
81 {
82 if file_type.is_dir() {
83 check_site(&entry.path(), delete);
84 }
85 }
86 }
87 }
88 Err(e) => {
89 log::error!(mirror_dir:?, e:err; "mirror directory error, maybe wrong base_dir specified");
90 }
91 }
92}
93
94fn find_base_dir_in_apt_mirror_config() -> Option<PathBuf> {
95 if let Ok(file) = File::open("/etc/apt/mirror.list") {
96 let re = Regex::new(r"set\s+base_path\s+([\w/-]+)").unwrap();
97
98 let reader = BufReader::new(file);
99
100 for line_result in reader.lines() {
101 if let Ok(line) = line_result {
102 if let Some(m) = re.captures(&line) {
103 return Some(PathBuf::from(m.get(1).unwrap().as_str()));
104 }
105 }
106 }
107 }
108
109 None
110}
111
112fn guess_base_dir(base_dir: Option<PathBuf>) -> PathBuf {
114 if let Some(base_dir) = base_dir {
115 log::info!(base_dir:?; "use user specified base_dir");
116 base_dir
117 } else if let Some(base_dir) = find_base_dir_in_apt_mirror_config() {
118 log::info!(base_dir:?; "use base_dir from /etc/apt/mirror.list");
119 base_dir
120 } else {
121 let base_dir = current_dir().unwrap(); log::info!(base_dir:?; "use current directory as base_dir");
123 base_dir
124 }
125}
126
127pub fn check_mirror_guessed(base_dir: Option<PathBuf>, delete: bool) {
128 check_mirror(guess_base_dir(base_dir), delete);
129}