blob: d6222082af4412d19576f039d6070409eff475bc (
plain)
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
|
use std::fs::read;
use std::path::{Path, PathBuf};
/// Name of tag file.
pub const CACHEDIR_TAG: &str = "CACHEDIR.TAG";
/// Prefix of contents of tag file.
pub const TAG: &str = "Signature: 8a477f597d28d172789f06886806bc55";
/// Is a given file a cache directory tag?
pub fn is_cachedir_tag(filename: &Path) -> Result<bool, CacheDirError> {
// Is the filename OK?
if let Some(basename) = filename.file_name() {
if basename != CACHEDIR_TAG {
return Ok(false);
}
}
// Does the file exist? It's OK if it doesn't, but we don't want
// to try to read it if it doesn't.
if !filename.exists() {
return Ok(false);
}
// Does the file start with the right prefix?
let data = read(filename).map_err(|e| CacheDirError::Read(filename.into(), e))?;
if data.len() >= TAG.len() {
Ok(&data[..TAG.len()] == TAG.as_bytes())
} else {
Ok(false)
}
}
#[derive(Debug, thiserror::Error)]
pub enum CacheDirError {
#[error("failed to read file {0}")]
Read(PathBuf, #[source] std::io::Error),
#[error("failed to write file {0}")]
Write(PathBuf, #[source] std::io::Error),
#[error("failed to delete file {0}")]
Remove(PathBuf, #[source] std::io::Error),
#[error(transparent)]
WalkDir(#[from] walkdir::Error),
}
|