pkg/net_backend/
curl_backend.rs1use std::{cell::RefCell, rc::Rc};
2use std::{
3 io::{Read, Write},
4 process::{Command, Stdio},
5};
6
7use crate::callback::Callback;
8use crate::net_backend::DownloadBackendWriter;
9
10use super::{DownloadBackend, DownloadError};
11
12#[derive(Clone, Default)]
14pub struct CurlBackend;
15
16impl DownloadBackend for CurlBackend {
17 fn new() -> Result<Self, DownloadError> {
18 Ok(Self)
19 }
20
21 fn download(
22 &self,
23 remote_path: &str,
24 _remote_len: Option<u64>,
25 writer: &mut DownloadBackendWriter,
26 _: Rc<RefCell<dyn Callback>>,
28 ) -> Result<(), DownloadError> {
29 let mut child = Command::new("curl")
30 .arg("-L")
31 .arg("-#")
32 .arg("-S")
33 .arg(remote_path)
34 .stdout(Stdio::piped())
35 .spawn()?;
36
37 let mut stdout = child.stdout.take().ok_or_else(|| {
38 DownloadError::IO(std::io::Error::from(std::io::ErrorKind::BrokenPipe))
39 })?;
40
41 let mut data = [0; 8192];
42 loop {
43 let count = stdout.read(&mut data)?;
44
45 if count == 0 {
46 break;
47 }
48
49 writer.write_all(&data[..count])?;
50 }
51
52 writer.flush()?;
53
54 let status = child.wait()?;
55
56 if !status.success() {
57 return Err(DownloadError::IO(std::io::Error::from(
58 std::io::ErrorKind::NotFound,
59 )));
60 }
61
62 Ok(())
63 }
64}