158 lines
5.4 KiB
C++
158 lines
5.4 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "ArchiveWriter.hpp"
|
|
#include "LibArchiveHelper.hpp"
|
|
#include <archive.h>
|
|
#include <archive_entry.h>
|
|
#include <iostream>
|
|
|
|
namespace openVulkanoCpp
|
|
{
|
|
ArchiveWriter::ArchiveWriter(const char* fileName, const std::shared_ptr<spdlog::logger>& logger)
|
|
: ArchiveWriter(fileName, ArchiveConfiguration::FromFileName(fileName), logger)
|
|
{}
|
|
|
|
ArchiveWriter::ArchiveWriter(const char* fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger)
|
|
: ArchiveBase(archive_write_new(), archive_entry_new(), logger)
|
|
{ //TODO error handling
|
|
ChkErr(archive_write_set_format(m_archive, archiveConfiguration.GetLibArchiveArchiveType()));
|
|
if (archiveConfiguration.type == ArchiveType::TAR)
|
|
{
|
|
ChkErr(archive_write_add_filter(m_archive, archiveConfiguration.GetLibArchiveCompressionType()));
|
|
}
|
|
if (archiveConfiguration.compression != CompressionType::NONE &&
|
|
archiveConfiguration.compressionLevel > 0)
|
|
{
|
|
std::string level = "compression-level=" + std::to_string(archiveConfiguration.compressionLevel);
|
|
ChkErr(archive_write_set_options(m_archive, level.c_str()));
|
|
}
|
|
ChkErr(archive_write_open_filename(m_archive, fileName));
|
|
}
|
|
|
|
ArchiveWriter::~ArchiveWriter()
|
|
{
|
|
archive_entry_free(m_archiveEntry);
|
|
}
|
|
|
|
void ArchiveWriter::Close()
|
|
{
|
|
archive_write_close(m_archive);
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const char* filePath)
|
|
{
|
|
std::filesystem::path path(filePath);
|
|
std::string fileName = path.filename().string();
|
|
if (std::filesystem::is_regular_file(path))
|
|
{
|
|
return AddFile(filePath, fileName.c_str());
|
|
}
|
|
else if (std::filesystem::is_directory(path))
|
|
{
|
|
AddFiles(filePath, fileName.c_str());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const char* fileName, const char* inArchiveName)
|
|
{
|
|
archive_entry_clear(m_archiveEntry);
|
|
std::unique_ptr<archive, decltype(archive_free)*> archiveDisk(archive_read_disk_new(), archive_free);
|
|
ChkErr(archive_read_disk_open(archiveDisk.get(), fileName));
|
|
ChkErr(archive_read_next_header2(archiveDisk.get(), m_archiveEntry));
|
|
//archive_read_disk_entry_from_file(archiveDisk, m_archiveEntry, -1, nullptr);
|
|
archive_entry_set_pathname(m_archiveEntry, inArchiveName);
|
|
ChkErr(archive_write_header(m_archive, m_archiveEntry));
|
|
int result = LibArchiveHelper::CopyArchiveData(archiveDisk.get(), m_archive);
|
|
ChkErr(result);
|
|
LibArchiveHelper::CheckError(result, archiveDisk.get(), m_logger);
|
|
ChkErr(archive_write_finish_entry(m_archive));
|
|
m_bytesWritten += archive_entry_size(m_archiveEntry);
|
|
return true;
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const char* inArchiveName, const void* buffer, size_t length)
|
|
{
|
|
FileDescription description = FileDescription::MakeDescriptionForFile(inArchiveName, length);
|
|
return AddFile(description, buffer);
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const FileDescription& description, const void* buffer)
|
|
{
|
|
WriteHeader(description);
|
|
bool ok = ChkErr(archive_write_data(m_archive, buffer, description.size));
|
|
ChkErr(archive_write_finish_entry(m_archive));
|
|
return ok;
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const char* fileName, const std::vector<std::pair<const void*, size_t>>& buffers)
|
|
{
|
|
size_t size = 0;
|
|
for(const auto& buffer : buffers)
|
|
{
|
|
if (buffer.first == nullptr) continue;
|
|
size += buffer.second;
|
|
}
|
|
FileDescription description = FileDescription::MakeDescriptionForFile(fileName, size);
|
|
return AddFile(description, buffers);
|
|
}
|
|
|
|
bool ArchiveWriter::AddFile(const FileDescription& description, const std::vector<std::pair<const void*, size_t>>& buffers)
|
|
{
|
|
WriteHeader(description);
|
|
for(const auto& buffer : buffers)
|
|
{
|
|
if (buffer.first == nullptr) continue;
|
|
if (!ChkErr(archive_write_data(m_archive, buffer.first, buffer.second)))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
ChkErr(archive_write_finish_entry(m_archive));
|
|
return true;
|
|
}
|
|
|
|
void ArchiveWriter::WriteHeader(const FileDescription& fileDescription)
|
|
{
|
|
archive_entry_clear(m_archiveEntry);
|
|
archive_entry_set_pathname_utf8(m_archiveEntry, fileDescription.path.c_str());
|
|
archive_entry_set_size(m_archiveEntry, fileDescription.size);
|
|
archive_entry_set_filetype(m_archiveEntry, LibArchiveHelper::GetFileType(fileDescription.type));
|
|
archive_entry_set_perm(m_archiveEntry, static_cast<mode_t>(fileDescription.permissions));
|
|
archive_entry_set_ctime(m_archiveEntry, fileDescription.createTime, 0);
|
|
archive_entry_set_mtime(m_archiveEntry, fileDescription.modTime, 0);
|
|
ChkErr(archive_write_header(m_archive, m_archiveEntry));
|
|
m_bytesWritten += fileDescription.size;
|
|
}
|
|
|
|
bool ArchiveWriter::AddFiles(const char* dirName)
|
|
{
|
|
return AddFiles(dirName, "");
|
|
}
|
|
|
|
bool ArchiveWriter::AddFiles(const char* dirName, const char* inArchiveDirName)
|
|
{
|
|
return AddFiles(std::filesystem::path(dirName), std::string(inArchiveDirName));
|
|
}
|
|
|
|
bool ArchiveWriter::AddFiles(const std::filesystem::path& dirName, const std::string& inArchiveDirName)
|
|
{
|
|
std::string sDirName = dirName.string();
|
|
AddFile(sDirName.c_str(), inArchiveDirName.c_str());
|
|
for(const auto& entry : std::filesystem::directory_iterator(dirName))
|
|
{
|
|
std::string fPath = inArchiveDirName + "/" + entry.path().filename().string();
|
|
if (entry.is_directory()) AddFiles(entry, fPath);
|
|
else
|
|
{
|
|
std::string entryName = entry.path().string();
|
|
AddFile(entryName.c_str(), fPath.c_str());
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
} |