Skip to content

Commit 7a2056a

Browse files
committed
add method for shredding cache database file
1 parent bb8f65f commit 7a2056a

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

src/cache.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::collections::HashMap;
2+
use std::fs::File;
3+
use std::io::{BufWriter, Write};
24
use std::path::Path;
35

46
use redb::{Database, Error, TableDefinition};
@@ -15,8 +17,10 @@ pub struct Cache {
1517
metadata: HashMap<String, CacheMetadataItem>, // Dictionary of metadata (and occasionally data [mostly for very small files])
1618
db: Option<Database>, // Pointer to database instance; None if not yet initialized or if failed to initialize
1719
db_ok: Option<bool>, // None by default, Some(true) if was able to initialize database, Some (false) if an error occured
20+
db_file_path: Option<String>, // Filesystem path to file used for storing database
1821
}
1922

23+
const FILE_WRITE_BUF_LEN: usize = 1024 * 100; // On-disk cache file write buffer size (in bytes)
2024
const TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("_");
2125

2226
impl Cache {
@@ -26,6 +30,7 @@ impl Cache {
2630
metadata: HashMap::new(),
2731
db: None,
2832
db_ok: None,
33+
db_file_path: db_file_path.clone(),
2934
};
3035

3136
if db_file_path.is_some() {
@@ -52,14 +57,14 @@ impl Cache {
5257
data: if self.db_ok.is_some() && self.db_ok.unwrap() {
5358
None
5459
} else {
55-
Some((data.to_owned()).to_vec())
60+
Some(data.to_owned().to_vec())
5661
},
5762
media_type: Some(media_type.to_owned()),
5863
charset: Some(charset),
5964
};
6065

6166
if (self.db_ok.is_none() || !self.db_ok.unwrap()) || data.len() <= self.min_file_size {
62-
cache_metadata_item.data = Some((data.to_owned()).to_vec());
67+
cache_metadata_item.data = Some(data.to_owned().to_vec());
6368
} else {
6469
match self.db.as_ref().unwrap().begin_write() {
6570
Ok(write_txn) => {
@@ -71,7 +76,7 @@ impl Cache {
7176
}
7277
Err(..) => {
7378
// Fall back to caching everything in memory
74-
cache_metadata_item.data = Some((data.to_owned()).to_vec());
79+
cache_metadata_item.data = Some(data.to_owned().to_vec());
7580
}
7681
}
7782
}
@@ -110,4 +115,40 @@ impl Cache {
110115
pub fn contains_key(&self, key: &str) -> bool {
111116
self.metadata.contains_key(key)
112117
}
118+
119+
pub fn destroy_database_file(&mut self) {
120+
if self.db_ok.is_none() || !self.db_ok.unwrap() {
121+
return;
122+
}
123+
124+
// Destroy database instance (prevents writes into file)
125+
self.db = None;
126+
self.db_ok = Some(false);
127+
128+
// Wipe database file
129+
if let Some(db_file_path) = self.db_file_path.to_owned() {
130+
// Overwrite file with zeroes
131+
if let Ok(temp_file) = File::options()
132+
.read(true)
133+
.write(true)
134+
.open(db_file_path.clone())
135+
{
136+
let mut buffer = [0; FILE_WRITE_BUF_LEN];
137+
let mut remaining_size: usize = temp_file.metadata().unwrap().len() as usize;
138+
let mut writer = BufWriter::new(temp_file);
139+
140+
while remaining_size > 0 {
141+
let bytes_to_write: usize = if remaining_size < FILE_WRITE_BUF_LEN {
142+
remaining_size
143+
} else {
144+
FILE_WRITE_BUF_LEN
145+
};
146+
let buffer = &mut buffer[..bytes_to_write];
147+
writer.write(buffer).unwrap();
148+
149+
remaining_size -= bytes_to_write;
150+
}
151+
}
152+
}
153+
}
113154
}

src/main.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,15 @@ const ASCII: &str = " \
5454
| | \\___/ | | \\ | | | | | | |
5555
|___| |__________| \\_____________________| |___| |___| |___|
5656
";
57-
const CACHE_ASSET_FILE_SIZE_THRESHOLD: usize = 1024 * 50; // Minimum file size for on-disk caching (in bytes)
57+
const CACHE_ASSET_FILE_SIZE_THRESHOLD: usize = 1024 * 10; // Minimum file size for on-disk caching (in bytes)
5858
const DEFAULT_NETWORK_TIMEOUT: u64 = 120;
5959
const DEFAULT_USER_AGENT: &str =
6060
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0";
6161

6262
fn main() {
6363
// Process CLI flags and options
6464
let mut cookie_file_path: Option<String> = None;
65+
let mut exit_code = 0;
6566
let mut options: Options = Options::default();
6667
let source;
6768
let destination;
@@ -164,7 +165,7 @@ fn main() {
164165
Ok(tempfile) => Some(tempfile),
165166
Err(_) => None,
166167
};
167-
let cache = Cache::new(
168+
let mut cache = Some(Cache::new(
168169
CACHE_ASSET_FILE_SIZE_THRESHOLD,
169170
if temp_cache_file.is_some() {
170171
Some(
@@ -178,7 +179,7 @@ fn main() {
178179
} else {
179180
None
180181
},
181-
);
182+
));
182183

183184
// Read and parse cookie file
184185
if let Some(opt_cookie_file) = cookie_file_path.clone() {
@@ -211,7 +212,7 @@ fn main() {
211212
}
212213
}
213214

214-
match create_monolithic_document(source, &options, &mut Some(cache)) {
215+
match create_monolithic_document(source, &options, &mut cache) {
215216
Ok(result) => {
216217
// Define output
217218
let mut output = Output::new(&destination).expect("could not prepare output");
@@ -222,7 +223,14 @@ fn main() {
222223
Err(error) => {
223224
print_error_message(&format!("Error: {}", error), &options);
224225

225-
process::exit(1);
226+
exit_code = 1;
226227
}
227228
}
229+
230+
// Clean up (shred database file)
231+
cache.unwrap().destroy_database_file();
232+
233+
if exit_code > 0 {
234+
process::exit(exit_code);
235+
}
228236
}

0 commit comments

Comments
 (0)