aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/tarfile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/tarfile.cc')
-rw-r--r--src/libutil/tarfile.cc130
1 files changed, 63 insertions, 67 deletions
diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc
index 2da169ba7..50e691a3d 100644
--- a/src/libutil/tarfile.cc
+++ b/src/libutil/tarfile.cc
@@ -2,83 +2,76 @@
#include <archive_entry.h>
#include "serialise.hh"
+#include "tarfile.hh"
namespace nix {
-struct TarArchive {
- struct archive * archive;
- Source * source;
- std::vector<unsigned char> buffer;
-
- void check(int err, const char * reason = "failed to extract archive: %s")
- {
- if (err == ARCHIVE_EOF)
- throw EndOfFile("reached end of archive");
- else if (err != ARCHIVE_OK)
- throw Error(reason, archive_error_string(this->archive));
- }
-
- TarArchive(Source & source) : buffer(4096)
- {
- this->archive = archive_read_new();
- this->source = &source;
-
- archive_read_support_filter_all(archive);
- archive_read_support_format_all(archive);
- check(archive_read_open(archive,
- (void *)this,
- TarArchive::callback_open,
- TarArchive::callback_read,
- TarArchive::callback_close),
- "failed to open archive: %s");
- }
-
- TarArchive(const Path & path)
- {
- this->archive = archive_read_new();
+static int callback_open(struct archive *, void * self)
+{
+ return ARCHIVE_OK;
+}
- archive_read_support_filter_all(archive);
- archive_read_support_format_all(archive);
- check(archive_read_open_filename(archive, path.c_str(), 16384), "failed to open archive: %s");
+static ssize_t callback_read(struct archive * archive, void * _self, const void * * buffer)
+{
+ auto self = (TarArchive *) _self;
+ *buffer = self->buffer.data();
+
+ try {
+ return self->source->read((char *) self->buffer.data(), 4096);
+ } catch (EndOfFile &) {
+ return 0;
+ } catch (std::exception & err) {
+ archive_set_error(archive, EIO, "Source threw exception: %s", err.what());
+ return -1;
}
+}
- TarArchive(const TarArchive &) = delete;
+static int callback_close(struct archive *, void * self)
+{
+ return ARCHIVE_OK;
+}
- void close()
- {
- check(archive_read_close(archive), "failed to close archive: %s");
- }
+void TarArchive::check(int err, const std::string & reason)
+{
+ if (err == ARCHIVE_EOF)
+ throw EndOfFile("reached end of archive");
+ else if (err != ARCHIVE_OK)
+ throw Error(reason, archive_error_string(this->archive));
+}
- ~TarArchive()
- {
- if (this->archive) archive_read_free(this->archive);
- }
+TarArchive::TarArchive(Source & source, bool raw)
+ : source(&source), buffer(4096)
+{
+ init();
+ if (!raw)
+ archive_read_support_format_all(archive);
+ else
+ archive_read_support_format_raw(archive);
+ check(archive_read_open(archive, (void *)this, callback_open, callback_read, callback_close), "Failed to open archive (%s)");
+}
-private:
+TarArchive::TarArchive(const Path & path)
+{
+ init();
+ archive_read_support_format_all(archive);
+ check(archive_read_open_filename(archive, path.c_str(), 16384), "failed to open archive: %s");
+}
- static int callback_open(struct archive *, void * self) {
- return ARCHIVE_OK;
- }
+void TarArchive::init()
+{
+ archive = archive_read_new();
+ archive_read_support_filter_all(archive);
+}
- static ssize_t callback_read(struct archive * archive, void * _self, const void * * buffer)
- {
- auto self = (TarArchive *)_self;
- *buffer = self->buffer.data();
-
- try {
- return self->source->read((char *) self->buffer.data(), 4096);
- } catch (EndOfFile &) {
- return 0;
- } catch (std::exception & err) {
- archive_set_error(archive, EIO, "source threw exception: %s", err.what());
- return -1;
- }
- }
+void TarArchive::close()
+{
+ check(archive_read_close(this->archive), "Failed to close archive (%s)");
+}
- static int callback_close(struct archive *, void * self) {
- return ARCHIVE_OK;
- }
-};
+TarArchive::~TarArchive()
+{
+ if (this->archive) archive_read_free(this->archive);
+}
static void extract_archive(TarArchive & archive, const Path & destDir)
{
@@ -92,13 +85,16 @@ static void extract_archive(TarArchive & archive, const Path & destDir)
struct archive_entry * entry;
int r = archive_read_next_header(archive.archive, &entry);
if (r == ARCHIVE_EOF) break;
- else if (r == ARCHIVE_WARN)
+ auto name = archive_entry_pathname(entry);
+ if (!name)
+ throw Error("cannot get archive member name: %s", archive_error_string(archive.archive));
+ if (r == ARCHIVE_WARN)
warn(archive_error_string(archive.archive));
else
archive.check(r);
archive_entry_set_pathname(entry,
- (destDir + "/" + archive_entry_pathname(entry)).c_str());
+ (destDir + "/" + name).c_str());
archive.check(archive_read_extract(archive.archive, entry, flags));
}