android_sparse/
read.rs

1//! Sparse image reading and encoding from raw images.
2
3use crate::{
4    block::Block,
5    ext::WriteBlock,
6    headers::{ChunkHeader, ChunkType, FileHeader},
7    result::{Error, Result},
8};
9use byteorder::{LittleEndian, ReadBytesExt};
10use crc::crc32::{self, Hasher32};
11use std::{
12    io::{prelude::*, BufReader, ErrorKind},
13    mem, slice,
14};
15
16const BLOCK_SIZE: usize = Block::SIZE as usize;
17const U32_BLOCK_SIZE: usize = BLOCK_SIZE / mem::size_of::<u32>();
18
19/// Reads sparse blocks from a sparse image.
20///
21/// Implements the `Iterator` trait, so sparse blocks can be read from
22/// a reader by iterating over it.
23pub struct Reader<R: Read> {
24    src: BufReader<R>,
25    current_chunk: Option<ChunkHeader>,
26    current_fill: Option<[u8; 4]>,
27    remaining_chunks: u32,
28    crc: Option<crc32::Digest>,
29    finished: bool,
30}
31
32impl<R: Read> Reader<R> {
33    /// Creates a new reader that reads from `r`.
34    ///
35    /// The created reader skips checksum verification in favor of
36    /// speed. To get a reader that does checksum verification, use
37    /// `Reader::with_crc` instead.
38    pub fn new(r: R) -> Result<Self> {
39        let mut src = BufReader::new(r);
40        let header = FileHeader::read_from(&mut src)?;
41        Ok(Self {
42            src,
43            current_chunk: None,
44            current_fill: None,
45            remaining_chunks: header.total_chunks,
46            crc: None,
47            finished: false,
48        })
49    }
50
51    /// Creates a new reader that reads from `r` and verifies all
52    /// included checksums.
53    pub fn with_crc(r: R) -> Result<Self> {
54        let mut reader = Self::new(r)?;
55        reader.crc = Some(crc32::Digest::new(crc32::IEEE));
56        Ok(reader)
57    }
58
59    fn next_block(&mut self) -> Result<Block> {
60        let mut chunk = match self.current_chunk.take() {
61            Some(c) => c,
62            None => ChunkHeader::read_from(&mut self.src)?,
63        };
64
65        let block = self.read_block(&mut chunk)?;
66        if let Some(digest) = self.crc.as_mut() {
67            digest.write_block(&block);
68        }
69
70        if chunk.chunk_size <= 1 {
71            self.remaining_chunks -= 1;
72            self.current_chunk = None;
73            self.current_fill = None;
74        } else {
75            chunk.chunk_size -= 1;
76            self.current_chunk = Some(chunk);
77        }
78
79        Ok(block)
80    }
81
82    fn read_block(&mut self, chunk: &mut ChunkHeader) -> Result<Block> {
83        match chunk.chunk_type {
84            ChunkType::Raw => {
85                let mut buf = [0; BLOCK_SIZE];
86                self.src.read_exact(&mut buf)?;
87                Ok(Block::Raw(Box::new(buf)))
88            }
89            ChunkType::Fill => {
90                let value = match self.current_fill {
91                    Some(v) => v,
92                    None => {
93                        self.current_fill = Some(read4(&mut self.src)?);
94                        self.current_fill.unwrap()
95                    }
96                };
97                Ok(Block::Fill(value))
98            }
99            ChunkType::DontCare => Ok(Block::Skip),
100            ChunkType::Crc32 => {
101                let checksum = self.src.read_u32::<LittleEndian>()?;
102                self.verify_checksum(checksum)?;
103                Ok(Block::Crc32(checksum))
104            }
105        }
106    }
107
108    fn verify_checksum(&self, checksum: u32) -> Result<()> {
109        if let Some(digest) = self.crc.as_ref() {
110            if digest.sum32() != checksum {
111                return Err(Error::Parse("Checksum does not match".into()));
112            }
113        }
114
115        Ok(())
116    }
117}
118
119impl<R: Read> Iterator for Reader<R> {
120    type Item = Result<Block>;
121
122    fn next(&mut self) -> Option<Self::Item> {
123        if self.finished {
124            return None;
125        }
126
127        let result = self.next_block();
128        self.finished = result.is_err() || self.remaining_chunks == 0;
129        Some(result)
130    }
131}
132
133fn read4<R: Read>(mut r: R) -> Result<[u8; 4]> {
134    let mut buf = [0; 4];
135    r.read_exact(&mut buf)?;
136    Ok(buf)
137}
138
139/// Wraps a block-sized buffer that is guaranteed to be 4-byte aligned.
140///
141/// This allows it to give out `&[u8]` and `&[u32]` views of the
142/// buffer. We need both kinds of views, since efficient checking for
143/// sparse blocks requires `&[u32]` while reading and writing only
144/// works on `&[u8]`.
145struct AlignedBuf([u32; U32_BLOCK_SIZE]);
146
147impl AlignedBuf {
148    fn new() -> Self {
149        AlignedBuf([0; U32_BLOCK_SIZE])
150    }
151
152    fn as_ref(&self) -> &[u8] {
153        let ptr = self.0.as_ptr().cast();
154        let len = self.0.len() * mem::size_of::<u32>();
155        unsafe { slice::from_raw_parts(ptr, len) }
156    }
157
158    fn as_mut(&mut self) -> &mut [u8] {
159        let ptr = self.0.as_mut_ptr().cast();
160        let len = self.0.len() * mem::size_of::<u32>();
161        unsafe { slice::from_raw_parts_mut(ptr, len) }
162    }
163
164    fn as_u32(&self) -> &[u32] {
165        &self.0
166    }
167
168    fn into_inner(self) -> [u8; BLOCK_SIZE] {
169        unsafe { mem::transmute::<[u32; U32_BLOCK_SIZE], [u8; BLOCK_SIZE]>(self.0) }
170    }
171}
172
173/// Reads blocks from a raw image and encodes them into sparse blocks.
174///
175/// Implements the `Iterator` trait, so sparse blocks can be read from
176/// an encoder by iterating over it.
177pub struct Encoder<R: Read> {
178    src: R,
179    finished: bool,
180}
181
182impl<R: Read> Encoder<R> {
183    /// Creates a new encoder that reads from `r`.
184    pub fn new(r: R) -> Result<Self> {
185        Ok(Self {
186            src: r,
187            finished: false,
188        })
189    }
190
191    fn read_block(&mut self) -> Result<Option<Block>> {
192        let mut buf = AlignedBuf::new();
193        let bytes_read = read_all(&mut self.src, buf.as_mut())?;
194
195        let block = match bytes_read {
196            0 => None,
197            _ => Some(Self::encode_block(buf)),
198        };
199        Ok(block)
200    }
201
202    fn encode_block(buf: AlignedBuf) -> Block {
203        if is_sparse(buf.as_u32()) {
204            let value = read4(buf.as_ref()).unwrap();
205            if value == [0; 4] {
206                Block::Skip
207            } else {
208                Block::Fill(value)
209            }
210        } else {
211            Block::Raw(Box::new(buf.into_inner()))
212        }
213    }
214}
215
216impl<R: Read> Iterator for Encoder<R> {
217    type Item = Result<Block>;
218
219    fn next(&mut self) -> Option<Self::Item> {
220        if self.finished {
221            return None;
222        }
223
224        match self.read_block() {
225            Ok(Some(c)) => Some(Ok(c)),
226            Ok(None) => {
227                self.finished = true;
228                None
229            }
230            Err(e) => {
231                self.finished = true;
232                Some(Err(e))
233            }
234        }
235    }
236}
237
238fn read_all<R: Read>(mut r: R, mut buf: &mut [u8]) -> Result<usize> {
239    let buf_size = buf.len();
240
241    while !buf.is_empty() {
242        match r.read(buf) {
243            Ok(0) => break,
244            Ok(n) => {
245                let tmp = buf;
246                buf = &mut tmp[n..];
247            }
248            Err(ref e) if e.kind() == ErrorKind::Interrupted => (),
249            Err(e) => return Err(e.into()),
250        };
251    }
252
253    Ok(buf_size - buf.len())
254}
255
256fn is_sparse(buf: &[u32]) -> bool {
257    let mut parts = buf.iter();
258    let first = parts.next().unwrap();
259    parts.all(|p| p == first)
260}
261
262#[cfg(test)]
263mod test {
264    use super::*;
265
266    const U8_BUF: &[u8] = &[0xaa; BLOCK_SIZE];
267    const U32_BUF: &[u32] = &[0xaaaaaaaa; U32_BLOCK_SIZE];
268    const HALF_BLOCK_SIZE: usize = BLOCK_SIZE / 2;
269
270    #[test]
271    fn aligned_buf() {
272        let mut buf = AlignedBuf::new();
273        buf.as_mut().write_all(U8_BUF).unwrap();
274
275        assert_eq!(buf.as_ref(), U8_BUF);
276        assert_eq!(buf.as_u32(), U32_BUF);
277
278        let content = buf.into_inner();
279        assert_eq!(&content[..], U8_BUF);
280    }
281
282    #[test]
283    fn read4() {
284        assert_eq!(super::read4(U8_BUF).unwrap(), [0xaa; 4]);
285    }
286
287    #[test]
288    fn read_all() {
289        let mut buf = [0; BLOCK_SIZE];
290
291        assert_eq!(
292            super::read_all(&U8_BUF[..HALF_BLOCK_SIZE], &mut buf).unwrap(),
293            HALF_BLOCK_SIZE
294        );
295        assert_eq!(&buf[..HALF_BLOCK_SIZE], &U8_BUF[..HALF_BLOCK_SIZE]);
296        assert_eq!(&buf[HALF_BLOCK_SIZE..], &[0; HALF_BLOCK_SIZE][..]);
297
298        assert_eq!(super::read_all(U8_BUF, &mut buf).unwrap(), BLOCK_SIZE);
299        assert_eq!(&buf[..], U8_BUF);
300    }
301
302    #[test]
303    fn is_sparse() {
304        assert!(super::is_sparse(U32_BUF));
305
306        let buf: Vec<_> = (0..U32_BLOCK_SIZE as u32).collect();
307        assert!(!super::is_sparse(&buf));
308    }
309}