Skip to content

Commit

Permalink
Download compressed gz image from remote source
Browse files Browse the repository at this point in the history
Accept url arguments for remote image download and copy.
Implements async support for use of reqwest. Bmap file is searched as in
local option in the current file with same name and the extension ".bmap"

Signed-off-by: Rafael Garcia Ruiz <rafael.garcia@collabora.com>
  • Loading branch information
Razaloc committed Oct 24, 2022
1 parent 90a3ff4 commit 2c88656
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
3 changes: 3 additions & 0 deletions bmap-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ anyhow = "1"
structopt = "0.3"
nix = "0.25"
flate2 = "1"
tokio = { version = "1.21.2", features = ["full"] }
reqwest = { version = "0.11.12"}
bytes = "1.2.1"
44 changes: 36 additions & 8 deletions bmap-rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use anyhow::{anyhow, bail, Context, Result};
use bmap::{Bmap, Discarder, SeekForward};
use bytes::Buf;
use flate2::read::GzDecoder;
use nix::unistd::ftruncate;
use reqwest::Url;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
Expand All @@ -14,7 +16,11 @@ struct Copy {
image: PathBuf,
dest: PathBuf,
}

#[derive(PartialEq)]
enum InputType {
Local,
Remote(Url),
}
#[derive(StructOpt, Debug)]
enum Command {
Copy(Copy),
Expand Down Expand Up @@ -75,7 +81,7 @@ impl SeekForward for Decoder {
}
}

fn setup_input(path: &Path) -> Result<Decoder> {
fn setup_local_input(path: &Path) -> Result<Decoder> {
let f = File::open(path)?;
match path.extension().and_then(OsStr::to_str) {
Some("gz") => {
Expand All @@ -86,12 +92,30 @@ fn setup_input(path: &Path) -> Result<Decoder> {
}
}

fn copy(c: Copy) -> Result<()> {
if !c.image.exists() {
async fn setup_remote_input(url: &Url) -> Result<Decoder> {
if url.to_file_path().unwrap().extension().unwrap() != "gz" {
bail!("Image file format not implemented")
}
let data = reqwest::get(url.clone()).await?.bytes().await?;
let reader = GzDecoder::new(data.reader());
Ok(Decoder::new(Discarder::new(reader)))
}

async fn copy(c: Copy) -> Result<()> {
let input_type = match Url::parse(c.image.to_str().unwrap()) {
Ok(url) => InputType::Remote(url),
Err(_) => InputType::Local,
};
if !c.image.exists() && input_type == InputType::Local {
bail!("Image file doesn't exist")
}

let bmap = find_bmap(&c.image).ok_or_else(|| anyhow!("Couldn't find bmap file"))?;
let bmap = match input_type {
InputType::Local => {
find_bmap(&c.image).ok_or_else(|| anyhow!("Couldn't find bmap file"))?
},
InputType::Remote(_) => find_bmap(Path::new(&c.image.file_name().unwrap())).ok_or_else(|| anyhow!("Couldn't find bmap file"))?,
};
println!("Found bmap file: {}", bmap.display());

let mut b = File::open(&bmap).context("Failed to open bmap file")?;
Expand All @@ -109,18 +133,22 @@ fn copy(c: Copy) -> Result<()> {
.context("Failed to truncate file")?;
}

let mut input = setup_input(&c.image)?;
let mut input = match input_type {
InputType::Local => setup_local_input(&c.image)?,
InputType::Remote(url) => setup_remote_input(&url).await?,
};
bmap::copy(&mut input, &mut output, &bmap)?;
println!("Done: Syncing...");
output.sync_all().expect("Sync failure");

Ok(())
}

fn main() -> Result<()> {
#[tokio::main]
async fn main() -> Result<()> {
let opts = Opts::from_args();

match opts.command {
Command::Copy(c) => copy(c),
Command::Copy(c) => copy(c).await,
}
}

0 comments on commit 2c88656

Please sign in to comment.