1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::fs::File;
use std::io::Read;
use fnv::FnvHashMap;
use once_cell::sync::OnceCell;
use petgraph::prelude::DiGraph;
use super::MagicRule;
use crate::fdo_magic::ruleset;
use crate::MIME;
static RUNTIME_RULES: OnceCell<Vec<Vec<u8>>> = OnceCell::new();
static ALIAS_STRING: OnceCell<String> = OnceCell::new();
static SUBCLASS_STRING: OnceCell<String> = OnceCell::new();
fn load_xdg_shared_magic() -> Vec<Vec<u8>> {
const SEARCH_PATHS: &[&str; 3] = &[
"/usr/share/mime/magic",
"/usr/local/share/mime/magic",
"$HOME/.local/share/mime/magic",
];
let files: Vec<Vec<u8>> = SEARCH_PATHS
.iter()
.map(|p| File::open(p).ok())
.filter_map(|f| f)
.map(|mut f| {
let mut buf = vec![];
f.read_to_end(&mut buf)
.expect("Failed to read magic file bytes");
buf
})
.collect();
if files.is_empty() {
panic!("No MIME magic files found in the XDG default paths");
}
files
}
fn load_concat_strings(paths: &[&str]) -> String {
let strings: Vec<String> = paths
.iter()
.map(|p| File::open(p).ok())
.filter_map(|f| f)
.map(|mut f| {
let mut s = String::new();
f.read_to_string(&mut s)
.expect("Failed to read aliases from file");
s
})
.collect();
strings.join("\n")
}
fn load_aliases() -> String {
const SEARCH_PATHS: &[&str; 3] = &[
"/usr/share/mime/aliases",
"/usr/local/share/mime/aliases",
"$HOME/.local/share/mime/aliases",
];
load_concat_strings(SEARCH_PATHS)
}
fn load_subclasses() -> String {
const SEARCH_PATHS: &[&str; 3] = &[
"/usr/share/mime/subclasses",
"/usr/local/share/mime/subclasses",
"$HOME/.local/share/mime/subclasses",
];
load_concat_strings(SEARCH_PATHS)
}
pub(crate) fn aliases() -> &'static str {
ALIAS_STRING.get_or_init(load_aliases)
}
pub(crate) fn subclasses() -> &'static str {
SUBCLASS_STRING.get_or_init(load_subclasses)
}
pub(crate) fn rules() -> Result<FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>>, String> {
let files = RUNTIME_RULES.get_or_init(load_xdg_shared_magic);
ruleset::from_multiple(files)
}