]> git.proxmox.com Git - proxmox-apt.git/blame - src/repositories/mod.rs
add more functions to check repositories
[proxmox-apt.git] / src / repositories / mod.rs
CommitLineData
b6be0f39
FE
1use std::collections::BTreeMap;
2use std::path::PathBuf;
3
4use anyhow::{bail, Error};
5
6mod repository;
7pub use repository::{
8 APTRepository, APTRepositoryFileType, APTRepositoryOption, APTRepositoryPackageType,
9};
10
11mod file;
76d3a5ba
FE
12pub use file::{APTRepositoryFile, APTRepositoryFileError, APTRepositoryInfo};
13
14mod release;
b6be0f39
FE
15
16const APT_SOURCES_LIST_FILENAME: &str = "/etc/apt/sources.list";
17const APT_SOURCES_LIST_DIRECTORY: &str = "/etc/apt/sources.list.d/";
18
19/// Calculates a common digest for successfully parsed repository files.
20///
21/// The digest is invariant with respect to file order.
22///
23/// Files without a digest are ignored.
24fn common_digest(files: &[APTRepositoryFile]) -> [u8; 32] {
25 let mut digests = BTreeMap::new();
26
27 for file in files.iter() {
28 digests.insert(file.path.clone(), &file.digest);
29 }
30
31 let mut common_raw = Vec::<u8>::with_capacity(digests.len() * 32);
32 for digest in digests.values() {
33 match digest {
34 Some(digest) => common_raw.extend_from_slice(&digest[..]),
35 None => (),
36 }
37 }
38
39 openssl::sha::sha256(&common_raw[..])
40}
41
76d3a5ba
FE
42/// Provides additional information about the repositories.
43///
44/// The kind of information can be:
45/// `warnings` for bad suites.
46/// `ignore-pre-upgrade-warning` when the next stable suite is configured.
47/// `badge` for official URIs.
48pub fn check_repositories(files: &[APTRepositoryFile]) -> Result<Vec<APTRepositoryInfo>, Error> {
49 let mut infos = vec![];
50
51 for file in files.iter() {
52 infos.append(&mut file.check_suites()?);
53 infos.append(&mut file.check_uris());
54 }
55
56 Ok(infos)
57}
58
b6be0f39
FE
59/// Returns all APT repositories configured in `/etc/apt/sources.list` and
60/// in `/etc/apt/sources.list.d` including disabled repositories.
61///
62/// Returns the succesfully parsed files, a list of errors for files that could
63/// not be read or parsed and a common digest for the succesfully parsed files.
64///
65/// The digest is guaranteed to be set for each successfully parsed file.
66pub fn repositories() -> Result<
67 (
68 Vec<APTRepositoryFile>,
69 Vec<APTRepositoryFileError>,
70 [u8; 32],
71 ),
72 Error,
73> {
74 let to_result = |files: Vec<APTRepositoryFile>, errors: Vec<APTRepositoryFileError>| {
75 let common_digest = common_digest(&files);
76
77 (files, errors, common_digest)
78 };
79
80 let mut files = vec![];
81 let mut errors = vec![];
82
83 let sources_list_path = PathBuf::from(APT_SOURCES_LIST_FILENAME);
84
85 let sources_list_d_path = PathBuf::from(APT_SOURCES_LIST_DIRECTORY);
86
87 match APTRepositoryFile::new(sources_list_path) {
88 Ok(Some(mut file)) => match file.parse() {
89 Ok(()) => files.push(file),
90 Err(err) => errors.push(err),
91 },
92 _ => bail!("internal error with '{}'", APT_SOURCES_LIST_FILENAME),
93 }
94
95 if !sources_list_d_path.exists() {
96 return Ok(to_result(files, errors));
97 }
98
99 if !sources_list_d_path.is_dir() {
100 errors.push(APTRepositoryFileError {
101 path: APT_SOURCES_LIST_DIRECTORY.to_string(),
102 error: "not a directory!".to_string(),
103 });
104 return Ok(to_result(files, errors));
105 }
106
107 for entry in std::fs::read_dir(sources_list_d_path)? {
108 let path = entry?.path();
109
110 match APTRepositoryFile::new(path) {
111 Ok(Some(mut file)) => match file.parse() {
112 Ok(()) => {
113 if file.digest.is_none() {
114 bail!("internal error - digest not set");
115 }
116 files.push(file);
117 }
118 Err(err) => errors.push(err),
119 },
120 Ok(None) => (),
121 Err(err) => errors.push(err),
122 }
123 }
124
125 Ok(to_result(files, errors))
126}