From f3b7b7d34b3bf2b1be18914577c96b66dead379a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 12 Dec 2017 17:33:03 +0100 Subject: Download and extract missing dependencies from github Using libcurl and libarchive --- src/Archive.cpp | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/Archive.cpp (limited to 'src/Archive.cpp') diff --git a/src/Archive.cpp b/src/Archive.cpp new file mode 100644 index 0000000..08ab42b --- /dev/null +++ b/src/Archive.cpp @@ -0,0 +1,171 @@ +#include "../include/Archive.hpp" +#include "../include/utils.hpp" +#include +#include +#include + +using namespace std; + +class FileHandler +{ + DISABLE_COPY(FileHandler) +public: + FileHandler(FILE *_file) : file(_file) + { + + } + + FileHandler(FileHandler &&other) + { + file = other.file; + other.file = nullptr; + } + + ~FileHandler() + { + fclose(file); + } + + FILE *file; +}; + +// libarchive code is modified version of: https://github.com/libarchive/libarchive/wiki/Examples#A_Complete_Extractor +namespace sibs +{ + static int copy_data(struct archive *ar, struct archive *aw) + { + int r; + const void *buff; + size_t size; + la_int64_t offset; + + while(true) + { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return ARCHIVE_OK; + else if (r < ARCHIVE_OK) + return r; + + r = archive_write_data_block(aw, buff, size, offset); + if (r < ARCHIVE_OK) + return r; + } + } + + Result Archive::extract(const char *source, const char *destination) + { + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int flags; + int r; + + /* Select which attributes we want to restore. */ + flags = ARCHIVE_EXTRACT_TIME; + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + + string rootName; + + a = archive_read_new(); + archive_read_support_format_all(a); + archive_read_support_compression_all(a); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); + archive_write_disk_set_standard_lookup(ext); + + + if ((r = archive_read_open_filename(a, source, 10240))) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + return Result::Err(errMsg); + } + + while(true) + { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + else if (r < ARCHIVE_OK) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(a); + return Result::Err(errMsg); + } + else if (r < ARCHIVE_WARN) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(a); + return Result::Err(errMsg); + } + + const char* currentFile = archive_entry_pathname(entry); + if(rootName.empty()) + rootName = currentFile; + + std::string fullOutputPath = destination; + fullOutputPath += (currentFile + (rootName.empty() ? 0 : rootName.size() - 1)); + archive_entry_set_pathname(entry, fullOutputPath.c_str()); + + r = archive_write_header(ext, entry); + if (r < ARCHIVE_OK) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(ext); + return Result::Err(errMsg); + } + else if (archive_entry_size(entry) > 0) { + r = copy_data(a, ext); + if (r < ARCHIVE_OK) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(ext); + return Result::Err(errMsg); + } + else if (r < ARCHIVE_WARN) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(ext); + return Result::Err(errMsg); + } + } + + r = archive_write_finish_entry(ext); + if (r < ARCHIVE_OK) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(ext); + return Result::Err(errMsg); + } + else if (r < ARCHIVE_WARN) + { + string errMsg = "Failed to extract archive: "; + errMsg += source; + errMsg += "; reason: "; + errMsg += archive_error_string(ext); + return Result::Err(errMsg); + } + } + + archive_read_close(a); + archive_read_free(a); + archive_write_close(ext); + archive_write_free(ext); + return Result::Ok(true); + } +} \ No newline at end of file -- cgit v1.2.3