mirror of
https://codeberg.org/demostf/backup.git
synced 2026-06-03 09:54:18 +02:00
double validate downloaded demo
This commit is contained in:
parent
08319e0dc9
commit
1887843fe2
5 changed files with 42 additions and 3 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -34,6 +34,7 @@ dependencies = [
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"main_error",
|
"main_error",
|
||||||
|
"md5",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ tokio = { version = "1.17.0", features = ["rt-multi-thread", "macros"] }
|
||||||
tracing = "0.1.33"
|
tracing = "0.1.33"
|
||||||
tracing-subscriber = "0.3.11"
|
tracing-subscriber = "0.3.11"
|
||||||
futures-util = "0.3.21"
|
futures-util = "0.3.21"
|
||||||
|
md5 = "0.7.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
@ -20,10 +20,21 @@ impl Backup {
|
||||||
async fn backup_demo(&self, name: &str, demo: &Demo) -> Result<(), Error> {
|
async fn backup_demo(&self, name: &str, demo: &Demo) -> Result<(), Error> {
|
||||||
info!("backing up");
|
info!("backing up");
|
||||||
|
|
||||||
let mut file = self.store.create(name).await?;
|
{
|
||||||
|
let file = self.store.create(name).await?;
|
||||||
|
demo.save(&self.client, file).await?;
|
||||||
|
}
|
||||||
|
|
||||||
demo.save(&self.client, &mut file).await?;
|
let digest = self.store.hash(name)?;
|
||||||
Ok(())
|
if digest == demo.hash || digest == [0; 16] {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let _ = self.store.remove(name);
|
||||||
|
Err(Error::DigestMismatch {
|
||||||
|
expected: demo.hash,
|
||||||
|
got: digest,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ pub enum Error {
|
||||||
Request(#[from] std::io::Error),
|
Request(#[from] std::io::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Api(#[from] demostf_client::Error),
|
Api(#[from] demostf_client::Error),
|
||||||
|
#[error("MD5 digest mismatch for downloaded demo, expected {expected:?}, received {got:?}")]
|
||||||
|
DigestMismatch { expected: [u8; 16], got: [u8; 16] },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
|
||||||
24
src/store.rs
24
src/store.rs
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
use md5::Context;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::{File, Permissions};
|
use std::fs::{File, Permissions};
|
||||||
|
use std::io::Read;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
|
@ -33,6 +35,28 @@ impl Store {
|
||||||
fs::remove_file(self.generate_path(name))
|
fs::remove_file(self.generate_path(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self, name: &str) -> Result<[u8; 16], Error> {
|
||||||
|
let path = self.generate_path(name);
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
|
||||||
|
let mut hash = Context::new();
|
||||||
|
|
||||||
|
let mut buff = vec![0; 1024 * 1024];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let read = file.read(&mut buff)?;
|
||||||
|
|
||||||
|
if read == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = &buff[0..read];
|
||||||
|
hash.consume(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(hash.compute().0)
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_path(&self, name: &str) -> PathBuf {
|
fn generate_path(&self, name: &str) -> PathBuf {
|
||||||
let mut path = self.basedir.clone();
|
let mut path = self.basedir.clone();
|
||||||
path.push(&name[0..2]);
|
path.push(&name[0..2]);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue