diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,11 @@ DESCRIPTION "A library for handling zip archives" PURPOSE "Optional for zip archives.") +find_package(SharedMimeInfo QUIET) +set_package_properties(SharedMimeInfo PROPERTIES + TYPE OPTIONAL + PURPOSE "Required for archive formats without an official mimetype.") + option(WITH_TEST_COVERAGE "Build with test coverage support" OFF) if (WITH_TEST_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") diff --git a/autotests/kerfuffle/data/simplearchive.tar.zst b/autotests/kerfuffle/data/simplearchive.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ + + + Tar archive (zstd-compressed) + + + diff --git a/plugins/libarchive/CMakeLists.txt b/plugins/libarchive/CMakeLists.txt --- a/plugins/libarchive/CMakeLists.txt +++ b/plugins/libarchive/CMakeLists.txt @@ -1,11 +1,19 @@ include_directories(${LibArchive_INCLUDE_DIRS}) +if(NOT LibArchive_VERSION VERSION_LESS "3.3.3") + set(ENABLE_ZSTD_SUPPORT ON BOOL) +endif() + ########### next target ############### set(SUPPORTED_LIBARCHIVE_READWRITE_MIMETYPES "application/x-tar;application/x-compressed-tar;application/x-bzip-compressed-tar;application/x-tarz;application/x-xz-compressed-tar;") set(SUPPORTED_LIBARCHIVE_READWRITE_MIMETYPES "${SUPPORTED_LIBARCHIVE_READWRITE_MIMETYPES}application/x-lzma-compressed-tar;application/x-lzip-compressed-tar;application/x-tzo;application/x-lrzip-compressed-tar;application/x-lz4-compressed-tar;") set(SUPPORTED_LIBARCHIVE_READONLY_MIMETYPES "application/vnd.debian.binary-package;application/x-deb;application/x-cd-image;application/x-bcpio;application/x-cpio;application/x-cpio-compressed;application/x-sv4cpio;application/x-sv4crc;") set(SUPPORTED_LIBARCHIVE_READONLY_MIMETYPES "${SUPPORTED_LIBARCHIVE_READONLY_MIMETYPES}application/x-rpm;application/x-source-rpm;application/vnd.ms-cab-compressed;application/x-xar;application/x-iso9660-appimage;application/x-archive;") +if(ENABLE_ZSTD_SUPPORT) + set(SUPPORTED_LIBARCHIVE_READWRITE_MIMETYPES "${SUPPORTED_LIBARCHIVE_READWRITE_MIMETYPES}application/x-zstd-compressed-tar;") +endif() + set(INSTALLED_LIBARCHIVE_PLUGINS "") set(kerfuffle_libarchive_readonly_SRCS libarchiveplugin.cpp readonlylibarchiveplugin.cpp ark_debug.cpp) @@ -49,6 +57,12 @@ \"application/x-lrzip-compressed-tar\", \"application/x-lz4-compressed-tar") +if(ENABLE_ZSTD_SUPPORT) + set(SUPPORTED_READWRITE_MIMETYPES + "${SUPPORTED_READWRITE_MIMETYPES}\", + \"application/x-zstd-compressed-tar") +endif() + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/kerfuffle_libarchive_readonly.json.cmake ${CMAKE_CURRENT_BINARY_DIR}/kerfuffle_libarchive_readonly.json) @@ -60,6 +74,10 @@ kerfuffle_add_plugin(kerfuffle_libarchive_readonly ${kerfuffle_libarchive_readonly_SRCS}) kerfuffle_add_plugin(kerfuffle_libarchive ${kerfuffle_libarchive_readwrite_SRCS}) +if(ENABLE_ZSTD_SUPPORT) + target_compile_definitions(kerfuffle_libarchive PRIVATE -DHAVE_ZSTD_SUPPORT) +endif() + target_link_libraries(kerfuffle_libarchive_readonly ${LibArchive_LIBRARIES}) target_link_libraries(kerfuffle_libarchive ${LibArchive_LIBRARIES}) @@ -82,3 +100,10 @@ else() message(WARNING "Could not find the lzop executable. Ark requires lzop to handle the tar.lzo archive format if libarchive >= 3.3 has been compiled without liblzo2 support.") endif() + +find_program(ZSTD zstd) +if(ZSTD) + message(STATUS "Found zstd executable: ${ZSTD}") +else() + message(WARNING "Could not find the zstd executable. Ark requires zstd to handle the tar.zst archive format if libarchive >= 3.3.3 has been compiled without libzstd support.") +endif() diff --git a/plugins/libarchive/kerfuffle_libarchive.json.cmake b/plugins/libarchive/kerfuffle_libarchive.json.cmake --- a/plugins/libarchive/kerfuffle_libarchive.json.cmake +++ b/plugins/libarchive/kerfuffle_libarchive.json.cmake @@ -116,5 +116,10 @@ "CompressionLevelDefault": 6, "CompressionLevelMax": 9, "CompressionLevelMin": 0 + }, + "application/x-zstd-compressed-tar": { + "CompressionLevelDefault": 3, + "CompressionLevelMax": 22, + "CompressionLevelMin": 1 } } diff --git a/plugins/libarchive/libarchiveplugin.cpp b/plugins/libarchive/libarchiveplugin.cpp --- a/plugins/libarchive/libarchiveplugin.cpp +++ b/plugins/libarchive/libarchiveplugin.cpp @@ -569,6 +569,8 @@ return QStringLiteral("lzop"); } else if (method == QLatin1String("lzma")) { return QStringLiteral("LZMA"); + } else if (method == QLatin1String("zstd")) { + return QStringLiteral("Zstandard"); } return QString(); } diff --git a/plugins/libarchive/readwritelibarchiveplugin.cpp b/plugins/libarchive/readwritelibarchiveplugin.cpp --- a/plugins/libarchive/readwritelibarchiveplugin.cpp +++ b/plugins/libarchive/readwritelibarchiveplugin.cpp @@ -294,6 +294,11 @@ case ARCHIVE_FILTER_LZ4: ret = archive_write_add_filter_lz4(m_archiveWriter.data()); break; +#ifdef HAVE_ZSTD_SUPPORT + case ARCHIVE_FILTER_ZSTD: + ret = archive_write_add_filter_zstd(m_archiveWriter.data()); + break; +#endif case ARCHIVE_FILTER_NONE: ret = archive_write_add_filter_none(m_archiveWriter.data()); break; @@ -343,9 +348,14 @@ qCDebug(ARK) << "Detected lrzip compression for new file"; ret = archive_write_add_filter_lrzip(m_archiveWriter.data()); requiresExecutable = true; - } else if (filename().right(3).toUpper() == QLatin1String("LZ4")) { - qCDebug(ARK) << "Detected lz4 compression for new file"; - ret = archive_write_add_filter_lz4(m_archiveWriter.data()); + } else if (filename().right(3).toUpper() == QLatin1String("LZ4")) { + qCDebug(ARK) << "Detected lz4 compression for new file"; + ret = archive_write_add_filter_lz4(m_archiveWriter.data()); +#ifdef HAVE_ZSTD_SUPPORT + } else if (filename().rightRef(3).compare(QLatin1String("zst"), Qt::CaseInsensitive) { + qCDebug(ARK) << "Detected zstd compression for new file"; + ret = archive_write_add_filter_zstd(m_archiveWriter.data()); +#endif } else if (filename().right(3).toUpper() == QLatin1String("TAR")) { qCDebug(ARK) << "Detected no compression for new file (pure tar)"; ret = archive_write_add_filter_none(m_archiveWriter.data());