aboutsummaryrefslogtreecommitdiff
path: root/src/Archive.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2017-12-12 17:33:03 +0100
committerdec05eba <dec05eba@protonmail.com>2017-12-12 17:34:16 +0100
commitf3b7b7d34b3bf2b1be18914577c96b66dead379a (patch)
treef24a08256bc959929d51045eb49283fcab7e8b54 /src/Archive.cpp
parentcfe578ec12198d09a9a89a2e0b40bccaa06aa8ae (diff)
Download and extract missing dependencies from github
Using libcurl and libarchive
Diffstat (limited to 'src/Archive.cpp')
-rw-r--r--src/Archive.cpp171
1 files changed, 171 insertions, 0 deletions
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 <cstring>
+#include <archive.h>
+#include <archive_entry.h>
+
+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<bool> 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<bool>::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<bool>::Err(errMsg);
+ }
+ else if (r < ARCHIVE_WARN)
+ {
+ string errMsg = "Failed to extract archive: ";
+ errMsg += source;
+ errMsg += "; reason: ";
+ errMsg += archive_error_string(a);
+ return Result<bool>::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<bool>::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<bool>::Err(errMsg);
+ }
+ else if (r < ARCHIVE_WARN)
+ {
+ string errMsg = "Failed to extract archive: ";
+ errMsg += source;
+ errMsg += "; reason: ";
+ errMsg += archive_error_string(ext);
+ return Result<bool>::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<bool>::Err(errMsg);
+ }
+ else if (r < ARCHIVE_WARN)
+ {
+ string errMsg = "Failed to extract archive: ";
+ errMsg += source;
+ errMsg += "; reason: ";
+ errMsg += archive_error_string(ext);
+ return Result<bool>::Err(errMsg);
+ }
+ }
+
+ archive_read_close(a);
+ archive_read_free(a);
+ archive_write_close(ext);
+ archive_write_free(ext);
+ return Result<bool>::Ok(true);
+ }
+} \ No newline at end of file