From 7e1d9138b5f088b9ff2e40008c3f2ca9fadcb2ac Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 28 Oct 2015 19:36:24 +0100 Subject: [PATCH] Add the deplete operation at the data stream It's used to read the content file up to the end to verify its CRC. --- cmdline/state.c | 21 +------------------ cmdline/stream.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-- cmdline/stream.h | 18 ++++++++++------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/cmdline/state.c b/cmdline/state.c index 88295c4e..79344ee7 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1564,26 +1564,7 @@ static void decoding_error(const char* path, STREAM* f) log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - - /* read until the end of the file */ - while (1) { - int c = sgetc(f); - if (c == EOF) { - break; - } - - /* keep the last four bytes */ - buf[0] = buf[1]; - buf[1] = buf[2]; - buf[2] = buf[3]; - buf[3] = c; - } - - if (serror(f)) { + if (sdeplete(f, buf) != 0) { /* LCOV_EXCL_START */ log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); exit(EXIT_FAILURE); diff --git a/cmdline/stream.c b/cmdline/stream.c index 82849022..b891e116 100644 --- a/cmdline/stream.c +++ b/cmdline/stream.c @@ -174,7 +174,11 @@ int shandle(STREAM* s) return s->handle[0].f; } -int sfill(STREAM* s) +/** + * Fill the read stream buffer. + * \return 0 if at least on char is read, or EOF on error. + */ +static int sfill(STREAM* s) { ssize_t ret; @@ -208,7 +212,45 @@ int sfill(STREAM* s) s->pos = s->buffer; s->end = s->buffer + ret; - return *s->pos++; + return 0; +} + +int sdeplete(STREAM* s, unsigned char* last) +{ + /* last four bytes */ + last[0] = 0; + last[1] = 0; + last[2] = 0; + last[3] = 0; + + while (1) { + /* increase the position up to 4 bytes before the end */ + if (s->pos + 4 <= s->end) + s->pos = s->end - 4; + + /* insert the last 4 bytes */ + while (s->pos < s->end) { + last[0] = last[1]; + last[1] = last[2]; + last[2] = last[3]; + last[3] = *s->pos++; + } + + /* fill again the buffer until the end of the file */ + if (sfill(s) != 0) { + /* on error fail */ + if (serror(s)) { + /* LCOV_EXCL_START */ + return EOF; + /* LCOV_EXCL_STOP */ + } + + /* on EOF terminate */ + break; + } + } + + return 0; } int sflush(STREAM* s) @@ -267,6 +309,14 @@ uint32_t scrc_stream(STREAM*s) return s->crc_stream ^ CRC_IV; } +int sgetc_uncached(STREAM* s) +{ + /* if at the end of the buffer, fill it */ + if (s->pos == s->end && sfill(s) != 0) + return EOF; + return *s->pos++; +} + int sgettok(STREAM* f, char* str, int size) { char* i = str; diff --git a/cmdline/stream.h b/cmdline/stream.h index 885f85ec..ec38d716 100644 --- a/cmdline/stream.h +++ b/cmdline/stream.h @@ -129,11 +129,11 @@ int sclose(STREAM* s); int shandle(STREAM* s); /** - * Fill the read stream buffer and read a char. - * \note Don't call this directly, but use sgetc(). - * \return The char read, or EOF on error. + * Read the stream until the end, and return the latest 4 chars. + * The CRC of the file is also computed, and you can get it using scrc(). + * \return 0 on success, or EOF on error. */ -int sfill(STREAM* s); +int sdeplete(STREAM* s, unsigned char* last); /** * Flush the write stream buffer. @@ -220,13 +220,19 @@ int ssync(STREAM* s); /****************************************************************************/ /* get */ +/** + * \internal Used by sgetc(). + * \note Don't call this directly, but use sgetc(). + */ +int sgetc_uncached(STREAM* s); + /** * Read a char. Like fgetc(). */ static inline int sgetc(STREAM* s) { - if (s->pos == s->end) - return sfill(s); + if (tommy_unlikely(s->pos == s->end)) + return sgetc_uncached(s); return *s->pos++; }