diff --git a/src/bin/download_sysext.rs b/src/bin/download_sysext.rs index aebfeb0..0edbbd8 100644 --- a/src/bin/download_sysext.rs +++ b/src/bin/download_sysext.rs @@ -19,6 +19,7 @@ use update_format_crau::delta_update; enum PackageStatus { ToDownload, DownloadIncomplete(omaha::FileSize), + DownloadFailed, BadChecksum, Unverified, BadSignature, @@ -93,7 +94,14 @@ impl<'a> Package<'a> { let path = into_dir.join(&*self.name); let mut file = File::create(path)?; - let res = ue_rs::download_and_hash(&client, self.url.clone(), &mut file).await?; + let res = match ue_rs::download_and_hash(&client, self.url.clone(), &mut file).await { + Ok(ok) => ok, + Err(err) => { + error!("Downloading failed with error {}", err); + self.status = PackageStatus::DownloadFailed; + return Err("unable to download data".into()); + } + }; self.verify_checksum(res.hash); Ok(()) @@ -262,7 +270,10 @@ async fn main() -> Result<(), Box> { for pkg in pkgs_to_dl.iter_mut() { pkg.check_download(&unverified_dir)?; - pkg.download(&unverified_dir, &client).await?; + match pkg.download(&unverified_dir, &client).await { + Ok(_) => (), + _ => return Err(format!("unable to download \"{}\"", pkg.name).into()), + }; let pkg_unverified = unverified_dir.join(&*pkg.name); let pkg_verified = output_dir.join(&*pkg.name); diff --git a/src/download.rs b/src/download.rs index 56ecb33..2df893c 100644 --- a/src/download.rs +++ b/src/download.rs @@ -1,6 +1,9 @@ use std::error::Error; use std::io::Write; use std::io; +use log::warn; + +use reqwest::StatusCode; use sha2::{Sha256, Digest}; @@ -19,6 +22,23 @@ where .send() .await?; + // Return immediately on download failure on the client side. + let status = res.status(); + + // TODO: handle redirect with retrying with a new URL or Attempt follow. + if status.is_redirection() { + warn!("redirect with status code {:?}", status); + } + + if !status.is_success() { + match status { + StatusCode::FORBIDDEN | StatusCode::NOT_FOUND => { + return Err(format!("cannnot fetch remotely with status code {:?}", status).into()); + } + _ => return Err(format!("general failure with status code {:?}", status).into()), + } + } + let mut hasher = Sha256::new(); let mut bytes_read = 0usize;