adb_rs/
push.rs

1use std::fs::File;
2use std::io::prelude::*;
3use std::io::BufReader;
4use std::io::SeekFrom;
5use std::path::Path;
6use std::time::SystemTime;
7
8use super::client::*;
9use super::sync::*;
10use crate::result::*;
11
12pub trait AdbPush {
13  fn push_reader<R: Read + Seek>(&mut self, r: R, remote_path: &str) -> AdbResult<()>;
14  fn push<P: AsRef<Path>>(&mut self, local_path: P, remote_path: &str) -> AdbResult<()>;
15}
16
17impl AdbPush for AdbConnection {
18  fn push_reader<R: Read + Seek>(&mut self, r: R, remote_path: &str) -> AdbResult<()> {
19    let mut r = r;
20
21    let size = r.seek(SeekFrom::End(0))?;
22    r.seek(SeekFrom::Start(0))?;
23
24    debug!("size = 0x{:x}", size);
25
26    let stream = self.open_stream("sync:")?;
27
28    debug!("STAT");
29    let stat = SyncCommand::new_stat(remote_path);
30    let packet = AdbStreamPacket::new_write(stat);
31    stream.send(packet)?;
32    stream.sync_recv_ok()?;
33    debug!("STAT ok");
34
35    let reply = stream.sync_recv_command(Command::A_WRTE)?;
36    debug!(
37      "STAT data received: payload len = 0x{:x}",
38      reply.payload.len()
39    );
40
41    stream.send_ok()?;
42
43    debug!("SEND");
44    let send = SyncCommand::new_send(remote_path, 0o100644);
45    let packet = AdbStreamPacket::new_write(send);
46    stream.send(packet)?;
47    stream.sync_recv_ok()?;
48    debug!("SEND ok");
49
50    let mut data = SyncCommand::new_data(self.max_data_len());
51    let mut bytes_sent = 0;
52
53    loop {
54      let n = data.read_payload_from(&mut r)?;
55      if n == 0 {
56        break;
57      }
58
59      let next_pos: u64 = bytes_sent + n as u64;
60
61      assert!(next_pos <= size);
62
63      let is_last_chunk = next_pos == size;
64      debug!("DATA [0x{:x}:0x{:x}]", bytes_sent, next_pos);
65      bytes_sent = bytes_sent + n as u64;
66
67      let packet = AdbStreamPacket::new_write(&data);
68
69      if is_last_chunk {
70        let now = SystemTime::now()
71          .duration_since(SystemTime::UNIX_EPOCH)
72          .unwrap()
73          .as_secs() as u32;
74        let done = SyncCommand::new_done(now);
75        let space = self.max_data_len() - data.len();
76        if space >= done.len() {
77          data.extend(done);
78          let packet = AdbStreamPacket::new_write(&data);
79          stream.send(packet)?;
80          stream.sync_recv_ok()?;
81          debug!("DATA last chunk ok");
82        } else {
83          let append_len = space;
84          if append_len > 0 {
85            data.extend(&done[0..append_len]);
86          }
87          let packet = AdbStreamPacket::new_write(&data);
88          stream.send(packet)?;
89          stream.sync_recv_ok()?;
90          stream.send(AdbStreamPacket::new_write(&done[append_len..]))?;
91          stream.sync_recv_ok()?;
92        }
93        break;
94      } else {
95        stream.send(packet)?;
96
97        stream.sync_recv_ok()?;
98        debug!("DATA chunk ok");
99      }
100    }
101
102    assert_eq!(bytes_sent as u64, size);
103
104    let reply = stream.sync_recv_command(Command::A_WRTE)?;
105    debug!("result = {}", String::from_utf8_lossy(&reply.payload));
106
107    stream.send_ok()?;
108
109    debug!("QUIT");
110    let quit = SyncCommand::new_quit();
111    let packet = AdbStreamPacket::new_write(quit);
112    stream.send(packet)?;
113
114    stream.sync_recv_ok()?;
115
116    stream.send_close()?;
117
118    stream.sync_recv_command(Command::A_CLSE)?;
119
120    Ok(())
121  }
122
123  fn push<P: AsRef<Path>>(&mut self, local_path: P, remote_path: &str) -> AdbResult<()> {
124    let file = File::open(local_path)?;
125    let r = BufReader::new(file);
126    self.push_reader(r, remote_path)
127  }
128}