mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-07 22:02:12 +08:00
archiver: add libarchive
Change-Id: I2ff7d879de55e18bedcbddce74f743ffe8755ca6
This commit is contained in:
@ -144,6 +144,7 @@ if(MSVC)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/include;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/msgpack-c/include;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/libarchive/libarchive;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/jsoncpp/include;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/yaml-cpp/include;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjlib/include;"
|
||||
@ -165,6 +166,7 @@ if(MSVC)
|
||||
"_WIN32_WINNT=0x0A00;"
|
||||
"ASIO_STANDALONE;"
|
||||
"STATIC_GETOPT;"
|
||||
"LIBARCHIVE_STATIC;"
|
||||
"OPENDHT_PROXY_CLIENT;"
|
||||
"OPENDHT_PROXY_SERVER;"
|
||||
"OPENDHT_PUSH_NOTIFICATIONS;"
|
||||
@ -226,40 +228,41 @@ if(MSVC)
|
||||
# Dependencies
|
||||
################################################################################
|
||||
|
||||
set(libAdditionalDependencies "${CMAKE_STATIC_LINKER_FLAGS} /LTCG ws2_32.lib
|
||||
advapi32.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avcodec.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avdevice.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avfilter.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avformat.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avutil.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/swresample.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/swscale.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libgnutls.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/lib_json.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libopendht.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/secp256k1.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/yaml-cpp/msvc/Release/libyaml-cppmd.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/portaudio.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libupnp.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/natpmp/msvc/Release/natpmp.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-core-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-simple-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsua2-lib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsua-lib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-ua-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjmedia/lib/pjmedia-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjlib-util/lib/pjlib-util-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjlib/lib/pjlib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjnath/lib/pjnath-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/fmt/msvc/Release/fmt.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/http_parser/x64/Release/http-parser.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/asio/asio/msvc/x64/Release/asio.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/openssl/out32dll/libeay32.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/openssl/out32dll/ssleay32.lib
|
||||
set(libAdditionalDependencies "${CMAKE_STATIC_LINKER_FLAGS} /LTCG ws2_32.lib
|
||||
advapi32.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avcodec.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avdevice.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avfilter.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avformat.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/avutil.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/swresample.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/ffmpeg/Build/win32/x64/bin/swscale.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libgnutls.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/lib_json.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libopendht.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/secp256k1.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/yaml-cpp/msvc/Release/libyaml-cppmd.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/portaudio.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/msvc/lib/x64/libupnp.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/natpmp/msvc/Release/natpmp.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/libarchive/msvc/libarchive/Release/archive_static.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-core-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-simple-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsua2-lib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsua-lib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjsip/lib/pjsip-ua-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjmedia/lib/pjmedia-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjlib-util/lib/pjlib-util-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjlib/lib/pjlib-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/pjproject/pjnath/lib/pjnath-x86_64-x64-vc15-Release.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/fmt/msvc/Release/fmt.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/http_parser/x64/Release/http-parser.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/asio/asio/msvc/x64/Release/asio.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/openssl/out32dll/libeay32.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/openssl/out32dll/ssleay32.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contrib/build/speexdsp/lib/libspeexdsp.lib
|
||||
/ignore:4006
|
||||
/ignore:4006
|
||||
"
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,8 @@
|
||||
"secp256k1",
|
||||
"speexdsp",
|
||||
"upnp",
|
||||
"yaml-cpp"
|
||||
"yaml-cpp",
|
||||
"libarchive"
|
||||
],
|
||||
"configuration": "ReleaseLib_win32",
|
||||
"project_paths": ["ring-daemon.vcxproj"]
|
||||
|
@ -302,6 +302,7 @@ PKG_CHECK_MODULES(PJPROJECT, libpjproject,, AC_MSG_ERROR([Missing pjproject file
|
||||
|
||||
PKG_CHECK_MODULES([YAMLCPP], [yaml-cpp >= 0.5.1],, AC_MSG_ERROR([yaml-cpp not found]))
|
||||
PKG_CHECK_MODULES([JSONCPP], [jsoncpp >= 1.6.5],, AC_MSG_ERROR([jsoncpp not found]))
|
||||
PKG_CHECK_MODULES([ARCHIVE], [libarchive >= 3.0],, AC_MSG_ERROR([libarchive not found]))
|
||||
|
||||
if test "${HAVE_ANDROID}" = "1"; then
|
||||
dnl Check for OpenSL
|
||||
|
1
contrib/src/libarchive/SHA512SUMS
Normal file
1
contrib/src/libarchive/SHA512SUMS
Normal file
@ -0,0 +1 @@
|
||||
2f9e2a551a6bcab56fb1a030b5d656df7299a3d151465aa02f0420d344d2fada49dee4755b3abff9095f62519e14dc9af8afa1695ecc6d5fdb4f0b28e6ede852 libarchive-3.4.0.tar.gz
|
17
contrib/src/libarchive/package.json
Normal file
17
contrib/src/libarchive/package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "libarchive",
|
||||
"version": "a53d711261f4d5bf2104d9c3616a8602a45ba196",
|
||||
"url": "https://github.com/libarchive/libarchive/archive/__VERSION__.tar.gz",
|
||||
"deps": [],
|
||||
"patches": [],
|
||||
"win_patches": [],
|
||||
"project_paths": ["msvc/libarchive/archive_static.vcxproj"],
|
||||
"with_env" : "",
|
||||
"custom_scripts": {
|
||||
"pre_build": [
|
||||
"mkdir msvc & cd msvc & cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TEST=OFF -DENABLE_TAR=OFF -DENABLE_CPIO=OFF -DENABLE_CAT=OFF -DENABLE_LIBXML2=OFF -G %CMAKE_GENERATOR%"
|
||||
],
|
||||
"build": [],
|
||||
"post_build": []
|
||||
}
|
||||
}
|
38
contrib/src/libarchive/rules.mak
Normal file
38
contrib/src/libarchive/rules.mak
Normal file
@ -0,0 +1,38 @@
|
||||
# LIBARCHIVE
|
||||
LIBARCHIVE_VERSION := 3.4.0
|
||||
LIBARCHIVE_URL := https://github.com/libarchive/libarchive/releases/download/v$(LIBARCHIVE_VERSION)/libarchive-$(LIBARCHIVE_VERSION).tar.gz
|
||||
|
||||
PKGS += libarchive
|
||||
ifeq ($(call need_pkg,"libarchive >= 3.4.0"),)
|
||||
PKGS_FOUND += libarchive
|
||||
endif
|
||||
|
||||
LIBARCHIVE_CMAKECONF := \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DENABLE_TEST=OFF \
|
||||
-DENABLE_TAR=OFF \
|
||||
-DENABLE_CPIO=OFF \
|
||||
-DENABLE_CAT=OFF \
|
||||
-DENABLE_LIBXML2=OFF
|
||||
|
||||
$(TARBALLS)/libarchive-$(LIBARCHIVE_VERSION).tar.gz:
|
||||
$(call download,$(LIBARCHIVE_URL))
|
||||
|
||||
.sum-libarchive: libarchive-$(LIBARCHIVE_VERSION).tar.gz
|
||||
|
||||
libarchive: libarchive-$(LIBARCHIVE_VERSION).tar.gz
|
||||
$(UNPACK)
|
||||
$(MOVE)
|
||||
|
||||
.libarchive: libarchive toolchain.cmake .sum-libarchive
|
||||
cd $< && mkdir -p buildlib
|
||||
ifdef HAVE_ANDROID
|
||||
cd $< && cp -R contrib/android/include/* $(PREFIX)/include
|
||||
endif
|
||||
cd $< && cd buildlib && $(HOSTVARS) $(CMAKE) .. $(LIBARCHIVE_CMAKECONF)
|
||||
cd $< && cd buildlib && $(MAKE) install
|
||||
ifdef HAVE_LINUX
|
||||
cd $< && cd $(PREFIX)/lib && rm libarchive.so*
|
||||
endif
|
||||
touch $@
|
@ -503,8 +503,8 @@ endif
|
||||
echo "set(CMAKE_CXX_COMPILER $(CXX))" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH $(PREFIX))" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)" >> $@
|
||||
echo "set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)" >> $@
|
||||
echo "set(CMAKE_BUILD_TYPE Release)" >> $@
|
||||
|
||||
# Default pattern rules
|
||||
|
@ -57,6 +57,7 @@ libring_la_LDFLAGS = \
|
||||
@GNUTLS_LIBS@ \
|
||||
@OPENDHT_LIBS@ \
|
||||
@SECP256K1_LIBS@ \
|
||||
@ARCHIVE_LIBS@ \
|
||||
@ZLIB_LIBS@ \
|
||||
@LIBSSL_LIBS@ \
|
||||
@LIBCRYPTO_LIBS@ \
|
||||
|
212
src/archiver.cpp
212
src/archiver.cpp
@ -32,6 +32,11 @@
|
||||
#include <json/json.h>
|
||||
#include <zlib.h>
|
||||
|
||||
extern "C" {
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
|
||||
@ -87,8 +92,8 @@ accountToJsonValue(const std::map<std::string, std::string>& details) {
|
||||
|
||||
int
|
||||
exportAccounts(const std::vector<std::string>& accountIDs,
|
||||
const std::string& filepath,
|
||||
const std::string& password)
|
||||
const std::string& filepath,
|
||||
const std::string& password)
|
||||
{
|
||||
if (filepath.empty() || !accountIDs.size()) {
|
||||
JAMI_ERR("Missing arguments");
|
||||
@ -304,4 +309,207 @@ openGzip(const std::string& path, const char *mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
// LIBARCHIVE DEFINITIONS
|
||||
//==========================
|
||||
using ArchivePtr = std::unique_ptr<archive, void(*)(archive*)>;
|
||||
using ArchiveEntryPtr = std::unique_ptr<archive_entry, void(*)(archive_entry*)>;
|
||||
|
||||
struct DataBlock {
|
||||
const void *buff;
|
||||
size_t size;
|
||||
int64_t offset;
|
||||
};
|
||||
|
||||
long readDataBlock(const ArchivePtr &a, DataBlock &b)
|
||||
{
|
||||
return archive_read_data_block(a.get(), &b.buff, &b.size, &b.offset);
|
||||
}
|
||||
|
||||
long writeDataBlock(const ArchivePtr &a, DataBlock &b)
|
||||
{
|
||||
return archive_write_data_block(a.get(), b.buff, b.size, b.offset);
|
||||
}
|
||||
|
||||
|
||||
ArchivePtr createArchiveReader() {
|
||||
ArchivePtr archivePtr{archive_read_new(), [](archive * a) {
|
||||
archive_read_close(a);
|
||||
archive_read_free(a);
|
||||
}};
|
||||
return archivePtr;
|
||||
}
|
||||
|
||||
static ArchivePtr createArchiveDiskWriter() {
|
||||
return {archive_write_disk_new(), [](archive * a) {
|
||||
archive_write_close(a);
|
||||
archive_write_free(a);
|
||||
}};
|
||||
}
|
||||
|
||||
//==========================
|
||||
|
||||
std::vector<std::string> listArchiveContent(const std::string &archivePath)
|
||||
{
|
||||
std::vector<std::string> fileNames;
|
||||
ArchivePtr archiveReader = createArchiveReader();
|
||||
struct archive_entry* entry;
|
||||
int r;
|
||||
|
||||
// Set reader formats(archive) and filters(compression)
|
||||
archive_read_support_filter_all(archiveReader.get());
|
||||
archive_read_support_format_all(archiveReader.get());
|
||||
|
||||
// Try to read the archive
|
||||
if ((r = archive_read_open_filename(archiveReader.get(), archivePath.c_str(), 10240))) {
|
||||
throw std::runtime_error(archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
while (archive_read_next_header(archiveReader.get(), &entry) == ARCHIVE_OK) {
|
||||
std::string fileEntry = archive_entry_pathname(entry) ? archive_entry_pathname(entry) : "Undefined";
|
||||
fileNames.push_back(fileEntry);
|
||||
}
|
||||
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
void uncompressArchive(const std::string &archivePath, const std::string &dir, const FileMatchPair& f)
|
||||
{
|
||||
int r;
|
||||
|
||||
ArchivePtr archiveReader = createArchiveReader();
|
||||
ArchivePtr archiveDiskWriter = createArchiveDiskWriter();
|
||||
struct archive_entry* entry;
|
||||
|
||||
int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_NO_HFS_COMPRESSION;
|
||||
|
||||
// Set reader formats(archive) and filters(compression)
|
||||
archive_read_support_filter_all(archiveReader.get());
|
||||
archive_read_support_format_all(archiveReader.get());
|
||||
|
||||
// Set written files flags and standard lookup(uid/gid)
|
||||
archive_write_disk_set_options(archiveDiskWriter.get(), flags);
|
||||
archive_write_disk_set_standard_lookup(archiveDiskWriter.get());
|
||||
|
||||
// Try to read the archive
|
||||
if ((r = archive_read_open_filename(archiveReader.get(), archivePath.c_str(), 10240))) {
|
||||
throw std::runtime_error("Open Archive: " + archivePath + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
while(true) {
|
||||
// Read headers until End of File
|
||||
r = archive_read_next_header(archiveReader.get(), &entry);
|
||||
if( r == ARCHIVE_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string fileEntry = archive_entry_pathname(entry) ? archive_entry_pathname(entry) : "Undefined";
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw std::runtime_error("Read file pathname: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
// File is ok, copy its header to the ext writer
|
||||
const auto& fileMatchPair = f(fileEntry);
|
||||
if(fileMatchPair.first) {
|
||||
std::string entryDestinationPath = dir + DIR_SEPARATOR_CH + fileMatchPair.second;
|
||||
archive_entry_set_pathname(entry, entryDestinationPath.c_str());
|
||||
r = archive_write_header(archiveDiskWriter.get(), entry);
|
||||
if (r != ARCHIVE_OK) {
|
||||
// Rollback if failed at a write operation
|
||||
fileutils::removeAll(dir);
|
||||
throw std::runtime_error("Write file header: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveDiskWriter.get()));
|
||||
} else {
|
||||
// Here both the reader and the writer have moved past the headers
|
||||
// Copying the data content
|
||||
DataBlock db;
|
||||
|
||||
while(true) {
|
||||
r = readDataBlock(archiveReader,db);
|
||||
if (r == ARCHIVE_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw std::runtime_error("Read file data: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
r = writeDataBlock(archiveDiskWriter, db);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
// Rollback if failed at a write operation
|
||||
fileutils::removeAll(dir);
|
||||
throw std::runtime_error("Write file data: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveDiskWriter.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> readFileFromArchive(const std::string &archivePath,
|
||||
const std::string &fileRelativePathName)
|
||||
{
|
||||
long r;
|
||||
ArchivePtr archiveReader = createArchiveReader();
|
||||
struct archive_entry* entry;
|
||||
|
||||
// Set reader formats(archive) and filters(compression)
|
||||
archive_read_support_filter_all(archiveReader.get());
|
||||
archive_read_support_format_all(archiveReader.get());
|
||||
|
||||
// Try to read the archive
|
||||
if ((r = archive_read_open_filename(archiveReader.get(), archivePath.c_str(), 10240))) {
|
||||
throw std::runtime_error("Open Archive: " + archivePath + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
while(true) {
|
||||
// Read headers until End of File
|
||||
r = archive_read_next_header(archiveReader.get(), &entry);
|
||||
if( r == ARCHIVE_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string fileEntry = archive_entry_pathname(entry) ? archive_entry_pathname(entry) : "";
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw std::runtime_error("Read file pathname: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
// File is ok and the reader has moved past the header
|
||||
if(fileEntry == fileRelativePathName){
|
||||
// Copying the data content
|
||||
DataBlock db;
|
||||
std::vector<uint8_t> fileContent;
|
||||
|
||||
while(true) {
|
||||
r = readDataBlock(archiveReader,db);
|
||||
if (r == ARCHIVE_EOF) {
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
throw std::runtime_error("Read file data: " + fileEntry + "\t" +
|
||||
archive_error_string(archiveReader.get()));
|
||||
}
|
||||
|
||||
if (fileContent.size() < static_cast<size_t>(db.offset)) {
|
||||
fileContent.resize(db.offset);
|
||||
}
|
||||
|
||||
auto dat = static_cast<const uint8_t*>(db.buff);
|
||||
// push the buffer data in the string stream
|
||||
fileContent.insert(fileContent.end(), dat, dat+db.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("File " + fileRelativePathName + " not found in the archive");
|
||||
}
|
||||
|
||||
}} // namespace jami::archiver
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
typedef struct gzFile_s *gzFile;
|
||||
|
||||
@ -35,6 +36,8 @@ namespace jami {
|
||||
*/
|
||||
namespace archiver {
|
||||
|
||||
using FileMatchPair = std::function<std::pair<bool,const std::string>(const std::string&)>;
|
||||
|
||||
/**
|
||||
* Create a protected archive containing a list of accounts
|
||||
* @param accountIDs The accounts to exports
|
||||
@ -43,8 +46,8 @@ namespace archiver {
|
||||
* @returns 0 for OK, error code otherwise
|
||||
*/
|
||||
int exportAccounts(const std::vector<std::string>& accountIDs,
|
||||
const std::string& filepath,
|
||||
const std::string& password);
|
||||
const std::string& filepath,
|
||||
const std::string& password);
|
||||
|
||||
/**
|
||||
* Read a protected archive and add accounts found in it
|
||||
@ -81,6 +84,37 @@ std::vector<uint8_t> decompressGzip(const std::string& path);
|
||||
*/
|
||||
gzFile openGzip(const std::string& path, const char *mode);
|
||||
|
||||
/**
|
||||
* @brief listArchiveContent
|
||||
* @param archivePath
|
||||
* @return list of relative file path names
|
||||
*/
|
||||
std::vector<std::string> listArchiveContent(const std::string& archivePath);
|
||||
|
||||
/**
|
||||
* @brief uncompressArchive Uncompresses an archive and puts the different files
|
||||
* in dir folder according to a FileMatchPair f
|
||||
* @param path
|
||||
* @param dir
|
||||
* @param f takes a file name relative path inside the archive like mysubfolder/myfile
|
||||
* and returns a pair (bool, new file name relative path)
|
||||
* Where the bool indicates if we should uncompress this file
|
||||
* and the new file name relative path puts the file in the directory dir under a different
|
||||
* relative path name like mynewsubfolder/myfile
|
||||
* @return void
|
||||
*/
|
||||
void uncompressArchive(const std::string& path, const std::string &dir, const FileMatchPair& f);
|
||||
|
||||
/**
|
||||
* @brief readFileFromArchive read a file from an archive without uncompressing
|
||||
* the whole archive
|
||||
* @param path archive path
|
||||
* @param fileRelativePathName file path relative path name in the archive
|
||||
* E.g: data/myfile.txt inside the archive
|
||||
* @return fileContent std::vector<uint8_t> that contains the file content
|
||||
*/
|
||||
std::vector<uint8_t> readFileFromArchive(const std::string &path,
|
||||
const std::string &fileRelativePathName);
|
||||
}
|
||||
|
||||
} // namespace jami
|
||||
|
Reference in New Issue
Block a user