double validate downloaded demo

This commit is contained in:
Robin Appelman 2022-05-09 23:30:01 +02:00
commit 1887843fe2
5 changed files with 42 additions and 3 deletions

View file

@ -20,10 +20,21 @@ impl Backup {
async fn backup_demo(&self, name: &str, demo: &Demo) -> Result<(), Error> {
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?;
Ok(())
let digest = self.store.hash(name)?;
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))]

View file

@ -16,6 +16,8 @@ pub enum Error {
Request(#[from] std::io::Error),
#[error(transparent)]
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]

View file

@ -1,6 +1,8 @@
use crate::Error;
use md5::Context;
use std::fs;
use std::fs::{File, Permissions};
use std::io::Read;
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
@ -33,6 +35,28 @@ impl Store {
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 {
let mut path = self.basedir.clone();
path.push(&name[0..2]);