summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools/imgtool/stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/imgtool/stream.cpp')
-rw-r--r--src/tools/imgtool/stream.cpp255
1 files changed, 208 insertions, 47 deletions
diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp
index bb0d95614f3..ed9814e504a 100644
--- a/src/tools/imgtool/stream.cpp
+++ b/src/tools/imgtool/stream.cpp
@@ -8,19 +8,178 @@
***************************************************************************/
+#include "stream.h"
+
+#include "imgtool.h"
+
+#include "corefile.h"
+#include "ioprocs.h"
+#include "unzip.h"
+
+#include <cassert>
#include <cstdio>
#include <cstring>
-#include <zlib.h>
-#include "unzip.h"
-#include "imgtool.h"
+#include <zlib.h> // for crc32
+
+
+namespace imgtool {
+
+namespace {
+
+class stream_read_wrapper : public virtual util::random_read
+{
+public:
+ stream_read_wrapper(stream::ptr &&stream, std::uint8_t filler) noexcept
+ : m_stream(stream.release())
+ , m_filler(filler)
+ , m_close(true)
+ {
+ assert(m_stream);
+ }
+
+ stream_read_wrapper(stream &stream, std::uint8_t filler) noexcept
+ : m_stream(&stream)
+ , m_filler(filler)
+ , m_close(false)
+ {
+ }
+
+ virtual ~stream_read_wrapper()
+ {
+ if (m_close)
+ delete m_stream;
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ m_stream->seek(offset, whence);
+ return std::error_condition();
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ result = m_stream->tell();
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ result = m_stream->size();
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = m_stream->read(buffer, length);
+ if (actual < length)
+ std::memset(reinterpret_cast<std::uint8_t *>(buffer) + actual, m_filler, length - actual);
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::uint64_t const pos = m_stream->tell();
+ m_stream->seek(offset, SEEK_SET);
+ actual = m_stream->read(buffer, length);
+ m_stream->seek(pos, SEEK_SET);
+ if (actual < length)
+ std::memset(reinterpret_cast<std::uint8_t *>(buffer) + actual, m_filler, length - actual);
+ return std::error_condition();
+ }
+
+protected:
+ stream *const m_stream;
+ std::uint8_t m_filler;
+ bool const m_close;
+};
+
+
+class stream_read_write_wrapper : public stream_read_wrapper, public util::random_read_write
+{
+public:
+ using stream_read_wrapper::stream_read_wrapper;
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::uint64_t const pos = m_stream->tell();
+ std::uint64_t size = m_stream->size();
+ if (size < pos)
+ {
+ m_stream->seek(size, SEEK_SET);
+ size += m_stream->fill(m_filler, pos - size);
+ }
+ actual = (size >= pos) ? m_stream->write(buffer, length) : 0U;
+ return (actual == length) ? std::error_condition() : std::errc::io_error;
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::uint64_t const pos = m_stream->tell();
+ std::uint64_t size = m_stream->size();
+ if (offset > size)
+ {
+ m_stream->seek(size, SEEK_SET);
+ size += m_stream->fill(m_filler, offset - size);
+ }
+ else
+ {
+ m_stream->seek(offset, SEEK_SET);
+ }
+ actual = (size >= offset) ? m_stream->write(buffer, length) : 0U;
+ m_stream->seek(pos, SEEK_SET);
+ return (actual == length) ? std::error_condition() : std::errc::io_error;
+ }
+};
+
+} // anonymous namespace
+
+
+util::random_read::ptr stream_read(stream::ptr &&s, std::uint8_t filler) noexcept
+{
+ util::random_read::ptr result;
+ if (s)
+ result.reset(new (std::nothrow) stream_read_wrapper(std::move(s), filler));
+ return result;
+}
+
+util::random_read::ptr stream_read(stream &s, std::uint8_t filler) noexcept
+{
+ util::random_read::ptr result(new (std::nothrow) stream_read_wrapper(s, filler));
+ return result;
+}
+
+util::random_read_write::ptr stream_read_write(stream::ptr &&s, std::uint8_t filler) noexcept
+{
+ util::random_read_write::ptr result;
+ if (s)
+ result.reset(new (std::nothrow) stream_read_write_wrapper(std::move(s), filler));
+ return result;
+}
+
+util::random_read_write::ptr stream_read_write(stream &s, std::uint8_t filler) noexcept
+{
+ util::random_read_write::ptr result(new (std::nothrow) stream_read_write_wrapper(s, filler));
+ return result;
+}
+
//-------------------------------------------------
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp)
+stream::stream(bool wp)
: imgtype(IMG_FILE)
, write_protect(wp)
, position(0)
@@ -35,7 +194,7 @@ imgtool::stream::stream(bool wp)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
+stream::stream(bool wp, util::core_file::ptr &&f)
: imgtype(IMG_FILE)
, write_protect(wp)
, position(0)
@@ -50,7 +209,7 @@ imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, std::size_t size)
+stream::stream(bool wp, std::size_t size)
: imgtype(IMG_MEM)
, write_protect(wp)
, position(0)
@@ -65,7 +224,7 @@ imgtool::stream::stream(bool wp, std::size_t size)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, std::size_t size, void *buf)
+stream::stream(bool wp, std::size_t size, void *buf)
: imgtype(IMG_MEM)
, write_protect(wp)
, position(0)
@@ -80,7 +239,7 @@ imgtool::stream::stream(bool wp, std::size_t size, void *buf)
// dtor
//-------------------------------------------------
-imgtool::stream::~stream()
+stream::~stream()
{
if (buffer)
free(buffer);
@@ -91,39 +250,39 @@ imgtool::stream::~stream()
// open_zip
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const char *subname, int read_or_write)
+stream::ptr stream::open_zip(const std::string &zipname, const char *subname, int read_or_write)
{
if (read_or_write)
- return imgtool::stream::ptr();
+ return stream::ptr();
/* check to see if the file exists */
FILE *f = fopen(zipname.c_str(), "r");
if (!f)
- return imgtool::stream::ptr();
+ return stream::ptr();
fclose(f);
- imgtool::stream::ptr imgfile(new imgtool::stream(true));
+ stream::ptr imgfile(new stream(true));
imgfile->imgtype = IMG_MEM;
util::archive_file::ptr z;
util::archive_file::open_zip(zipname, z);
if (!z)
- return imgtool::stream::ptr();
+ return stream::ptr();
int zipent = z->first_file();
while ((zipent >= 0) && subname && strcmp(subname, z->current_name().c_str()))
zipent = z->next_file();
if (zipent < 0)
- return imgtool::stream::ptr();
+ return stream::ptr();
imgfile->filesize = z->current_uncompressed_length();
imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(z->current_uncompressed_length()));
if (!imgfile->buffer)
- return imgtool::stream::ptr();
+ return stream::ptr();
- if (z->decompress(imgfile->buffer, z->current_uncompressed_length()) != util::archive_file::error::NONE)
- return imgtool::stream::ptr();
+ if (z->decompress(imgfile->buffer, z->current_uncompressed_length()))
+ return stream::ptr();
return imgfile;
}
@@ -134,7 +293,7 @@ imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const
// open
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read_or_write)
+stream::ptr stream::open(const std::string &filename, int read_or_write)
{
static const uint32_t write_modes[] =
{
@@ -143,7 +302,7 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
OPEN_FLAG_READ | OPEN_FLAG_WRITE,
OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE
};
- imgtool::stream::ptr s;
+ stream::ptr s;
char c;
// maybe we are just a ZIP?
@@ -152,13 +311,13 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
util::core_file::ptr f = nullptr;
auto const filerr = util::core_file::open(filename, write_modes[read_or_write], f);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
if (!read_or_write)
{
int const len = filename.size();
- /* can't open the file; try opening ZIP files with other names */
+ // can't open the file; try opening ZIP files with other names
std::vector<char> buf(len + 1);
strcpy(&buf[0], filename.c_str());
@@ -177,11 +336,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
return s;
}
- /* ah well, it was worth a shot */
- return imgtool::stream::ptr();
+ // ah well, it was worth a shot
+ return stream::ptr();
}
- imgtool::stream::ptr imgfile(new imgtool::stream(read_or_write ? false : true, std::move(f)));
+ stream::ptr imgfile(new stream(read_or_write ? false : true, std::move(f)));
// normal file
return imgfile;
@@ -192,11 +351,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
// open_write_stream
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_write_stream(int size)
+stream::ptr stream::open_write_stream(int size)
{
- imgtool::stream::ptr imgfile(new imgtool::stream(false, size));
+ stream::ptr imgfile(new stream(false, size));
if (!imgfile->buffer)
- return imgtool::stream::ptr();
+ return stream::ptr();
return imgfile;
}
@@ -206,9 +365,9 @@ imgtool::stream::ptr imgtool::stream::open_write_stream(int size)
// open_mem
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz)
+stream::ptr stream::open_mem(void *buf, size_t sz)
{
- imgtool::stream::ptr imgfile(new imgtool::stream(false, sz, buf));
+ stream::ptr imgfile(new stream(false, sz, buf));
return imgfile;
}
@@ -218,7 +377,7 @@ imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz)
// core_file
//-------------------------------------------------
-util::core_file *imgtool::stream::core_file()
+util::core_file *stream::core_file()
{
return (imgtype == IMG_FILE) ? file.get() : nullptr;
}
@@ -228,7 +387,7 @@ util::core_file *imgtool::stream::core_file()
// read
//-------------------------------------------------
-uint32_t imgtool::stream::read(void *buf, uint32_t sz)
+uint32_t stream::read(void *buf, uint32_t sz)
{
uint32_t result = 0;
@@ -262,7 +421,7 @@ uint32_t imgtool::stream::read(void *buf, uint32_t sz)
// write
//-------------------------------------------------
-uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
+uint32_t stream::write(const void *buf, uint32_t sz)
{
void *new_buffer;
uint32_t result = 0;
@@ -317,7 +476,7 @@ uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
// size
//-------------------------------------------------
-uint64_t imgtool::stream::size() const
+uint64_t stream::size() const
{
return filesize;
}
@@ -327,7 +486,7 @@ uint64_t imgtool::stream::size() const
// getptr
//-------------------------------------------------
-void *imgtool::stream::getptr()
+void *stream::getptr()
{
void *ptr;
@@ -349,7 +508,7 @@ void *imgtool::stream::getptr()
// seek
//-------------------------------------------------
-int imgtool::stream::seek(int64_t pos, int where)
+int stream::seek(int64_t pos, int where)
{
switch(where)
{
@@ -377,7 +536,7 @@ int imgtool::stream::seek(int64_t pos, int where)
// tell
//-------------------------------------------------
-uint64_t imgtool::stream::tell()
+uint64_t stream::tell()
{
return position;
}
@@ -387,7 +546,7 @@ uint64_t imgtool::stream::tell()
// transfer
//-------------------------------------------------
-uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz)
+uint64_t stream::transfer(stream &dest, stream &source, uint64_t sz)
{
uint64_t result = 0;
uint64_t readsz;
@@ -407,7 +566,7 @@ uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &sourc
// transfer_all
//-------------------------------------------------
-uint64_t imgtool::stream::transfer_all(imgtool::stream &dest, imgtool::stream &source)
+uint64_t stream::transfer_all(stream &dest, stream &source)
{
return transfer(dest, source, source.size());
}
@@ -417,7 +576,7 @@ uint64_t imgtool::stream::transfer_all(imgtool::stream &dest, imgtool::stream &s
// crc
//-------------------------------------------------
-int imgtool::stream::crc(unsigned long *result)
+int stream::crc(unsigned long *result)
{
size_t sz;
void *ptr;
@@ -451,12 +610,12 @@ int imgtool::stream::crc(unsigned long *result)
// file_crc
//-------------------------------------------------
-int imgtool::stream::file_crc(const char *fname, unsigned long *result)
+int stream::file_crc(const char *fname, unsigned long *result)
{
int err;
- imgtool::stream::ptr f;
+ stream::ptr f;
- f = imgtool::stream::open(fname, OSD_FOPEN_READ);
+ f = stream::open(fname, OSD_FOPEN_READ);
if (!f)
return IMGTOOLERR_FILENOTFOUND;
@@ -469,7 +628,7 @@ int imgtool::stream::file_crc(const char *fname, unsigned long *result)
// fill
//-------------------------------------------------
-uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz)
+uint64_t stream::fill(unsigned char b, uint64_t sz)
{
uint64_t outsz;
char buf[1024];
@@ -490,7 +649,7 @@ uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz)
// is_read_only
//-------------------------------------------------
-bool imgtool::stream::is_read_only()
+bool stream::is_read_only()
{
return write_protect;
}
@@ -500,7 +659,7 @@ bool imgtool::stream::is_read_only()
// putc
//-------------------------------------------------
-uint32_t imgtool::stream::putc(char c)
+uint32_t stream::putc(char c)
{
return write(&c, 1);
}
@@ -510,7 +669,7 @@ uint32_t imgtool::stream::putc(char c)
// puts
//-------------------------------------------------
-uint32_t imgtool::stream::puts(const char *s)
+uint32_t stream::puts(const char *s)
{
return write(s, strlen(s));
}
@@ -520,7 +679,7 @@ uint32_t imgtool::stream::puts(const char *s)
// printf
//-------------------------------------------------
-uint32_t imgtool::stream::printf(const char *fmt, ...)
+uint32_t stream::printf(const char *fmt, ...)
{
va_list va;
char buf[256];
@@ -531,3 +690,5 @@ uint32_t imgtool::stream::printf(const char *fmt, ...)
return puts(buf);
}
+
+} // namespace imgtool