diff options
author | Max Kellermann <max@musicpd.org> | 2020-09-04 18:35:21 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-09-04 18:35:21 +0200 |
commit | 67c7116f058666fbcc050d6d879778f41665b447 (patch) | |
tree | 5660ae62bb3d751b0a1b928b3a1c144b28aa9f4a /src/archive | |
parent | 9aa432c07838256536c39b00d14c04462862b4fc (diff) | |
parent | db8b419b8c3aa738efb3fa7b5de7b2894ced6cde (diff) |
Merge branch 'v0.21.x' into master
Diffstat (limited to 'src/archive')
-rw-r--r-- | src/archive/plugins/Bzip2ArchivePlugin.cxx | 52 | ||||
-rw-r--r-- | src/archive/plugins/Iso9660ArchivePlugin.cxx | 24 | ||||
-rw-r--r-- | src/archive/plugins/ZzipArchivePlugin.cxx | 25 |
3 files changed, 49 insertions, 52 deletions
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx index 3ea1b755a..3234eafa8 100644 --- a/src/archive/plugins/Bzip2ArchivePlugin.cxx +++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx @@ -59,9 +59,9 @@ public: class Bzip2InputStream final : public InputStream { std::shared_ptr<InputStream> input; - bool eof = false; + bz_stream bzstream{}; - bz_stream bzstream; + bool eof = false; char buffer[5000]; @@ -69,7 +69,7 @@ public: Bzip2InputStream(std::shared_ptr<InputStream> _input, const char *uri, Mutex &mutex); - ~Bzip2InputStream() override; + ~Bzip2InputStream() noexcept override; /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; @@ -81,25 +81,6 @@ private: bool FillBuffer(); }; -/* single archive handling allocation helpers */ - -inline void -Bzip2InputStream::Open() -{ - bzstream.bzalloc = nullptr; - bzstream.bzfree = nullptr; - bzstream.opaque = nullptr; - - bzstream.next_in = (char *)buffer; - bzstream.avail_in = 0; - - int ret = BZ2_bzDecompressInit(&bzstream, 0, 0); - if (ret != BZ_OK) - throw std::runtime_error("BZ2_bzDecompressInit() has failed"); - - SetReady(); -} - /* archive open && listing routine */ static std::unique_ptr<ArchiveFile> @@ -118,10 +99,16 @@ Bzip2InputStream::Bzip2InputStream(std::shared_ptr<InputStream> _input, :InputStream(_uri, _mutex), input(std::move(_input)) { - Open(); + bzstream.next_in = (char *)buffer; + + int ret = BZ2_bzDecompressInit(&bzstream, 0, 0); + if (ret != BZ_OK) + throw std::runtime_error("BZ2_bzDecompressInit() has failed"); + + SetReady(); } -Bzip2InputStream::~Bzip2InputStream() +Bzip2InputStream::~Bzip2InputStream() noexcept { BZ2_bzDecompressEnd(&bzstream); } @@ -151,22 +138,18 @@ Bzip2InputStream::FillBuffer() size_t Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length) { - const ScopeUnlock unlock(mutex); - - int bz_result; - size_t nbytes = 0; - if (eof) return 0; + const ScopeUnlock unlock(mutex); + bzstream.next_out = (char *)ptr; bzstream.avail_out = length; do { - if (!FillBuffer()) - return 0; + const bool had_input = FillBuffer(); - bz_result = BZ2_bzDecompress(&bzstream); + const int bz_result = BZ2_bzDecompress(&bzstream); if (bz_result == BZ_STREAM_END) { eof = true; @@ -175,9 +158,12 @@ Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length) if (bz_result != BZ_OK) throw std::runtime_error("BZ2_bzDecompress() has failed"); + + if (!had_input && bzstream.avail_out == length) + throw std::runtime_error("Unexpected end of bzip2 file"); } while (bzstream.avail_out == length); - nbytes = length - bzstream.avail_out; + const size_t nbytes = length - bzstream.avail_out; offset += nbytes; return nbytes; diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 1b4540957..78b17d5b1 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -148,24 +148,22 @@ Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor) class Iso9660InputStream final : public InputStream { std::shared_ptr<Iso9660> iso; - iso9660_stat_t *statbuf; + const lsn_t lsn; public: Iso9660InputStream(std::shared_ptr<Iso9660> _iso, const char *_uri, Mutex &_mutex, - iso9660_stat_t *_statbuf) + lsn_t _lsn, offset_type _size) :InputStream(_uri, _mutex), - iso(std::move(_iso)), statbuf(_statbuf) { - size = statbuf->size; + iso(std::move(_iso)), + lsn(_lsn) + { + size = _size; seekable = true; SetReady(); } - ~Iso9660InputStream() override { - free(statbuf); - } - /* virtual methods from InputStream */ [[nodiscard]] bool IsEOF() const noexcept override; size_t Read(std::unique_lock<Mutex> &lock, @@ -185,8 +183,12 @@ Iso9660ArchiveFile::OpenStream(const char *pathname, throw FormatRuntimeError("not found in the ISO file: %s", pathname); + const lsn_t lsn = statbuf->lsn; + const offset_type size = statbuf->size; + free(statbuf); + return std::make_unique<Iso9660InputStream>(iso, pathname, mutex, - statbuf); + lsn, size); } size_t @@ -197,7 +199,7 @@ Iso9660InputStream::Read(std::unique_lock<Mutex> &, int readed = 0; int no_blocks, cur_block; - size_t left_bytes = statbuf->size - offset; + size_t left_bytes = size - offset; if (left_bytes < read_size) { no_blocks = CEILING(left_bytes, ISO_BLOCKSIZE); @@ -210,7 +212,7 @@ Iso9660InputStream::Read(std::unique_lock<Mutex> &, cur_block = offset / ISO_BLOCKSIZE; - readed = iso->SeekRead(ptr, statbuf->lsn + cur_block, no_blocks); + readed = iso->SeekRead(ptr, lsn + cur_block, no_blocks); if (readed != no_blocks * ISO_BLOCKSIZE) throw FormatRuntimeError("error reading ISO file at lsn %lu", diff --git a/src/archive/plugins/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx index c1e48e557..582a16b04 100644 --- a/src/archive/plugins/ZzipArchivePlugin.cxx +++ b/src/archive/plugins/ZzipArchivePlugin.cxx @@ -34,6 +34,8 @@ #include <utility> +#include <inttypes.h> /* for PRIoffset (PRIu64) */ + struct ZzipDir { ZZIP_DIR *const dir; @@ -56,8 +58,9 @@ class ZzipArchiveFile final : public ArchiveFile { std::shared_ptr<ZzipDir> dir; public: - explicit ZzipArchiveFile(std::shared_ptr<ZzipDir> &&_dir) - :dir(std::move(_dir)) {} + template<typename D> + explicit ZzipArchiveFile(D &&_dir) noexcept + :dir(std::forward<D>(_dir)) {} void Visit(ArchiveVisitor &visitor) override; @@ -93,11 +96,12 @@ class ZzipInputStream final : public InputStream { ZZIP_FILE *const file; public: - ZzipInputStream(std::shared_ptr<ZzipDir> _dir, const char *_uri, + template<typename D> + ZzipInputStream(D &&_dir, const char *_uri, Mutex &_mutex, ZZIP_FILE *_file) :InputStream(_uri, _mutex), - dir(std::move(_dir)), file(_file) { + dir(std::forward<D>(_dir)), file(_file) { //we are seekable (but its not recommendent to do so) seekable = true; @@ -108,7 +112,7 @@ public: SetReady(); } - ~ZzipInputStream() override { + ~ZzipInputStream() noexcept override { zzip_file_close(file); } @@ -148,12 +152,17 @@ ZzipInputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t read_size) { const ScopeUnlock unlock(mutex); - int ret = zzip_file_read(file, ptr, read_size); - if (ret < 0) + zzip_ssize_t nbytes = zzip_file_read(file, ptr, read_size); + if (nbytes < 0) throw std::runtime_error("zzip_file_read() has failed"); + if (nbytes == 0 && !IsEOF()) + throw FormatRuntimeError("Unexpected end of file %s" + " at %" PRIoffset " of %" PRIoffset, + GetURI(), GetOffset(), GetSize()); + offset = zzip_tell(file); - return ret; + return nbytes; } bool |