From 75b0f9da00a0c3283df4e3e1022ef92d1cc3c864 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 31 Aug 2015 09:53:18 -0700 Subject: [PATCH] Ensure EOF is returned when gz finishes Previously we'd return an I/O error after the first EOF was returned as we'd try to verify the checksum again, and this commit now sets a flag to indicate that the checksum has already been verified so we can always return EOF after the first one is seen. Closes #25 --- src/gz.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/gz.rs b/src/gz.rs index f73e10a4b..8d5a5fc2a 100644 --- a/src/gz.rs +++ b/src/gz.rs @@ -58,6 +58,7 @@ pub struct Builder { pub struct DecoderReader { inner: CrcReader>, header: Header, + finished: bool, } /// A structure representing the header of a gzip stream. @@ -383,7 +384,8 @@ impl DecoderReader { filename: filename, comment: comment, mtime: mtime, - } + }, + finished: false, }); fn bad_header() -> io::Error { @@ -411,6 +413,9 @@ impl DecoderReader { pub fn header(&self) -> &Header { &self.header } fn finish(&mut self) -> io::Result<()> { + if self.finished { + return Ok(()) + } let ref mut buf = [0u8; 8]; { let mut len = 0; @@ -433,6 +438,7 @@ impl DecoderReader { ((buf[7] as u32) << 24); if crc != self.inner.crc().sum() as u32 { return Err(corrupt()) } if amt != self.inner.crc().amt() { return Err(corrupt()) } + self.finished = true; Ok(()) } } @@ -539,4 +545,17 @@ mod tests { assert_eq!(res, vec![0, 2, 4, 6]); } + + #[test] + fn keep_reading_after_end() { + let mut e = EncoderWriter::new(Vec::new(), Default); + e.write_all(b"foo bar baz").unwrap(); + let inner = e.finish().unwrap(); + let mut d = DecoderReader::new(&inner[..]).unwrap(); + let mut s = String::new(); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, "foo bar baz"); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, "foo bar baz"); + } }