Created
November 9, 2020 23:30
-
-
Save jackbergus/14fc158488d8822067aefe2ead4779c4 to your computer and use it in GitHub Desktop.
Reading a .tar.xx file using a more C++ structured fashion via libarchive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.16) | |
project(read_archive) | |
set(CMAKE_CXX_STANDARD 14) | |
find_library(LibArchive 3.4.0) | |
add_executable(read_archive main.cpp) | |
target_link_libraries(read_archive archive) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <archive.h> | |
#include <archive_entry.h> | |
#include <fcntl.h> | |
template <size_t buffer_size = 1024> | |
class ReadArchiveBuffer { | |
char buff[buffer_size]; | |
size_t size; | |
struct archive *a; | |
std::string path; | |
public: | |
ReadArchiveBuffer(archive *a, const std::string& path) : a(a), path(path) { size = -1; } | |
ReadArchiveBuffer() : ReadArchiveBuffer(nullptr, "") { size = 0; }; | |
ReadArchiveBuffer(const ReadArchiveBuffer&) = default; | |
ReadArchiveBuffer& operator=(const ReadArchiveBuffer&) = default; | |
bool readNext(struct iovec& data) { | |
if (a) { | |
size = archive_read_data(a, buff, 1024); | |
} | |
if (size <= 0) { | |
data.iov_len = 0; | |
data.iov_base = nullptr; | |
return false; | |
} else { | |
data.iov_base = buff; | |
data.iov_len = size; | |
return true; | |
} | |
} | |
std::string filename() const { return path; } | |
}; | |
template <size_t buffer_size = 1024> | |
class ReadArchive { | |
public: | |
ReadArchive(const std::string& file_name, size_t block_size = 10240) : ReadArchive{} { | |
a = archive_read_new(); | |
archive_read_support_format_all(a); | |
archive_read_support_compression_all(a); | |
if ((r = archive_read_open_filename(a, file_name.c_str(), block_size))) | |
throw std::runtime_error("Cannot read file: " + file_name); | |
this->operator++(); | |
} | |
ReadArchive() { | |
a = nullptr; | |
entry = nullptr; | |
r = ARCHIVE_EOF; | |
} | |
~ReadArchive() { | |
archive_read_close(a); | |
archive_read_free(a); | |
} | |
bool doStop() { | |
return ((r == ARCHIVE_EOF) || (r < ARCHIVE_OK) || (r < ARCHIVE_WARN) || (archive_entry_size(entry) <= 0)); | |
} | |
ReadArchive& operator++() { | |
r = archive_read_next_header(a, &entry); | |
while ((r != ARCHIVE_EOF) && (r >= ARCHIVE_OK) && (r >= ARCHIVE_WARN) && (archive_entry_size(entry) == 0)) { | |
r = archive_read_next_header(a, &entry); | |
} | |
} | |
ReadArchiveBuffer<buffer_size> operator*() { | |
std::string filename = archive_entry_pathname(entry); | |
return {a, filename}; | |
} | |
ReadArchiveBuffer<buffer_size> operator->() { | |
std::string filename = archive_entry_pathname(entry); | |
return {a, filename}; | |
} | |
private: | |
struct archive *a; | |
struct archive_entry *entry; | |
int r; | |
}; | |
int main() { | |
for (ReadArchive<> ra{"/path/to/some/file.tar.xz"}; !ra.doStop(); ++ra) { | |
ReadArchiveBuffer<> buff = *ra; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << buff.filename() << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
struct iovec data; | |
while (buff.readNext(data)) { | |
std::cout << std::string((const char*)data.iov_base, data.iov_len); // Printing string data | |
} | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment