Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <archive.h>
- #include <archive_entry.h>
- #include <filesystem>
- #include <iostream>
- #include <iterator>
- #include <list>
- #include <memory>
- #include <utility>
- #include <vector>
- class File {
- private:
- std::string path;
- std::vector<uint8_t> data;
- public:
- File(struct archive *arch, struct archive_entry *arch_entry)
- : path{archive_entry_pathname(arch_entry)},
- data(static_cast<size_t>(archive_entry_size(arch_entry))) {
- size_t ret = archive_read_data(arch, this->data.data(), this->data.size());
- if (ret != this->data.size()) {
- throw std::runtime_error("Could not read archive entry.");
- }
- }
- std::string GetPath() {
- return this->path;
- }
- std::vector<uint8_t> &GetData() {
- return this->data;
- }
- };
- class Archive {
- private:
- std::filesystem::path file_path;
- public:
- using unique_archive = std::unique_ptr<struct archive, decltype(&::archive_read_free)>;
- using unique_archive_entry =
- std::unique_ptr<struct archive_entry, decltype(&::archive_entry_free)>;
- Archive(const std::filesystem::path &path) : file_path(path) {
- }
- class iterator {
- private:
- std::filesystem::path arch_path;
- unique_archive arch;
- unique_archive_entry entry;
- public:
- using iterator_category = std::forward_iterator_tag;
- using value_type = File;
- using difference_type = void;
- iterator(const std::filesystem::path &arch_path)
- : arch_path(arch_path), arch{archive_read_new(), archive_read_free},
- entry{archive_entry_new(), archive_entry_free} {
- int ret;
- ret = archive_read_support_filter_all(this->arch.get());
- if (ret != ARCHIVE_OK) {
- throw std::runtime_error("Could not set archive filter.");
- }
- ret = archive_read_support_format_all(this->arch.get());
- if (ret != ARCHIVE_OK) {
- throw std::runtime_error("Could not set archive format.");
- }
- ret = archive_read_open_filename_w(this->arch.get(), arch_path.wstring().c_str(), 0);
- if (ret != ARCHIVE_OK) {
- throw std::runtime_error("Could not open archive.");
- }
- ret = archive_read_next_header2(this->arch.get(), this->entry.get());
- if (ret != ARCHIVE_OK) {
- throw std::runtime_error("Could not iterate over archive.");
- }
- }
- iterator(const std::filesystem::path &arch_path, struct archive *a, struct archive_entry *e)
- : arch_path(arch_path), arch(a, archive_read_free), entry(e, archive_entry_free) {
- }
- iterator &operator++() {
- int ret = archive_read_next_header2(this->arch.get(), this->entry.get());
- if (ret == ARCHIVE_EOF) {
- this->arch.reset();
- this->entry.reset();
- } else if (ret != ARCHIVE_OK) {
- throw std::runtime_error("Could not iterate over archive.");
- }
- return *this;
- }
- File operator*() const {
- return File{this->arch.get(), this->entry.get()};
- }
- friend bool operator==(const iterator &a, const iterator &b) {
- if (a.entry.get() == nullptr && b.entry.get() == nullptr) {
- return a.arch_path == b.arch_path;
- } else if (a.entry.get() == nullptr || b.entry.get() == nullptr) {
- return false;
- }
- std::string a_path{archive_entry_pathname(a.entry.get())},
- b_path{archive_entry_pathname(b.entry.get())};
- return a_path == b_path && a.arch_path == b.arch_path;
- }
- friend bool operator!=(const iterator &a, const iterator &b) {
- if (a.entry.get() == nullptr && b.entry.get() == nullptr) {
- return a.arch_path != b.arch_path;
- } else if (a.entry.get() == nullptr || b.entry.get() == nullptr) {
- return true;
- }
- std::string a_path{archive_entry_pathname(a.entry.get())},
- b_path{archive_entry_pathname(b.entry.get())};
- return a_path != b_path || a.arch_path != b.arch_path;
- }
- };
- iterator begin() {
- return iterator{this->file_path};
- }
- iterator end() {
- return iterator{this->file_path, nullptr, nullptr};
- }
- };
- int main() {
- // std::unique_ptr<struct archive, decltype(&::archive_read_free)> a{archive_read_new(),
- // archive_read_free};
- // int r;
- // archive_read_support_filter_all(a.get());
- // archive_read_support_format_all(a.get());
- // r = archive_read_open_filename(a.get(), "archive.tar", 10240); // Note 1
- // if (r != ARCHIVE_OK)
- // return EXIT_FAILURE;
- // std::unique_ptr<struct archive_entry, decltype(&::archive_entry_free)> entry{
- // archive_entry_new2(a.get()), archive_entry_free},
- // entry2{archive_entry_new2(a.get()), archive_entry_free};
- // while (archive_read_next_header2(a.get(), entry.get()) == ARCHIVE_OK &&
- // archive_read_next_header2(a.get(), entry2.get()) == ARCHIVE_OK) {
- // printf("%s\n", archive_entry_pathname(entry.get()));
- // printf("%s\n", archive_entry_pathname(entry2.get()));
- // archive_read_data_skip(a.get()); // Note 2
- // }
- Archive arch{"archive.tar"};
- for (File f : arch) {
- for (File g : arch) {
- std::cout << g.GetPath() << std::endl;
- }
- std::cout << f.GetPath() << std::endl;
- std::cout << "Size: " << f.GetData().size() << std::endl;
- std::cout << std::string{f.GetData().begin(), f.GetData().end()} << std::endl;
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement