104 lines
3 KiB
C
104 lines
3 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <archive.h>
|
||
|
#include <archive_entry.h>
|
||
|
|
||
|
inline void CreateArchive(std::vector<std::string> paths, const std::string& destinationPath, const std::string& rootDir)
|
||
|
{
|
||
|
archive* archive;
|
||
|
archive_entry *entry;
|
||
|
|
||
|
entry = archive_entry_new();
|
||
|
|
||
|
archive = archive_write_new();
|
||
|
|
||
|
archive_write_add_filter_none(archive);
|
||
|
archive_write_set_format_zip(archive);
|
||
|
|
||
|
archive_write_open_filename(archive, destinationPath.c_str());
|
||
|
for(unsigned int i = 0; i < paths.size(); i++)
|
||
|
{
|
||
|
std::fstream file(paths[i].c_str(), std::ios::binary | std::ios::in);
|
||
|
if(file.is_open())
|
||
|
{
|
||
|
file.seekg(0, std::ios::end);
|
||
|
long size = file.tellg();
|
||
|
file.seekg(0, std::ios::beg);
|
||
|
|
||
|
std::vector<char> buffer(size);
|
||
|
if(size == 0 || file.read(&buffer[0], size))
|
||
|
{
|
||
|
std::string fileName = paths[i].substr(paths[i].rfind('\\') + 1);
|
||
|
|
||
|
if(rootDir != "")
|
||
|
fileName = Utility::RemoveSubstrings(fileName, {rootDir + "/"});
|
||
|
|
||
|
archive_entry_set_pathname(entry, fileName.c_str());
|
||
|
archive_entry_set_size(entry, size);
|
||
|
archive_entry_set_filetype(entry, AE_IFREG);
|
||
|
archive_entry_set_perm(entry, 0644);
|
||
|
archive_write_header(archive, entry);
|
||
|
|
||
|
archive_write_data(archive, size == 0 ? "" : &buffer[0], size);
|
||
|
|
||
|
file.close();
|
||
|
continue;
|
||
|
}
|
||
|
file.close();
|
||
|
|
||
|
archive_entry_clear(entry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
archive_entry_free(entry);
|
||
|
|
||
|
archive_write_close(archive);
|
||
|
#ifndef MACOS
|
||
|
archive_write_free(archive); //for some reason this is undefined under macos
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//modified from https://github.com/libarchive/libarchive/wiki/Examples#A_Complete_Extractor
|
||
|
inline void copy_data(archive* ar, archive* aw)
|
||
|
{
|
||
|
const void* buff;
|
||
|
size_t size;
|
||
|
off_t offset;
|
||
|
|
||
|
while(archive_read_data_block(ar, &buff, &size, &offset) != ARCHIVE_EOF)
|
||
|
archive_write_data_block(aw, buff, size, offset);
|
||
|
}
|
||
|
|
||
|
inline void ExtractArchive(const std::string& archivePath, const std::string& destPath)
|
||
|
{
|
||
|
archive* a, *ext;
|
||
|
archive_entry* entry;
|
||
|
|
||
|
a = archive_read_new();
|
||
|
archive_read_support_format_all(a);
|
||
|
archive_read_support_filter_all(a);
|
||
|
|
||
|
ext = archive_write_disk_new();
|
||
|
archive_write_disk_set_standard_lookup(ext);
|
||
|
|
||
|
archive_read_open_filename(a, archivePath.c_str(), 16384);
|
||
|
while(archive_read_next_header(a, &entry) != ARCHIVE_EOF)
|
||
|
{
|
||
|
const char* currentFile = archive_entry_pathname(entry);
|
||
|
std::string fullOutputPath = destPath + currentFile;
|
||
|
|
||
|
archive_entry_set_pathname(entry, fullOutputPath.c_str());
|
||
|
|
||
|
archive_write_header(ext, entry);
|
||
|
|
||
|
if (archive_entry_size(entry) > 0)
|
||
|
copy_data(a, ext);
|
||
|
|
||
|
archive_write_finish_entry(ext);
|
||
|
}
|
||
|
|
||
|
archive_read_close(a);
|
||
|
archive_read_free(a);
|
||
|
archive_write_close(ext);
|
||
|
archive_write_free(ext);
|
||
|
}
|