summaryrefslogtreecommitdiff
path: root/src/archive
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-09-04 18:35:21 +0200
committerMax Kellermann <max@musicpd.org>2020-09-04 18:35:21 +0200
commit67c7116f058666fbcc050d6d879778f41665b447 (patch)
tree5660ae62bb3d751b0a1b928b3a1c144b28aa9f4a /src/archive
parent9aa432c07838256536c39b00d14c04462862b4fc (diff)
parentdb8b419b8c3aa738efb3fa7b5de7b2894ced6cde (diff)
Merge branch 'v0.21.x' into master
Diffstat (limited to 'src/archive')
-rw-r--r--src/archive/plugins/Bzip2ArchivePlugin.cxx52
-rw-r--r--src/archive/plugins/Iso9660ArchivePlugin.cxx24
-rw-r--r--src/archive/plugins/ZzipArchivePlugin.cxx25
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