[file-roller/wip/jtojnar/7zip: 2/3] command-7z: Add support for the official 7-Zip project
- From: Jan Tojnar <jtojnar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller/wip/jtojnar/7zip: 2/3] command-7z: Add support for the official 7-Zip project
- Date: Tue, 21 Jun 2022 10:15:56 +0000 (UTC)
commit 65e9cfcbe5fa1a382c3622f63143b07667cb1544
Author: Jan Tojnar <jtojnar gmail com>
Date: Mon Jun 20 23:33:47 2022 +0200
command-7z: Add support for the official 7-Zip project
Quoting from the project’s README:
Now there are two different ports of 7-Zip for Linux/macOS:
1) p7zip - another port of 7-Zip for Linux, made by an independent developer.
The latest version of p7zip now is 16.02, and that p7zip 16.02 is outdated now.
2) 7-Zip for Linux/macOS - this package - it's new code with all changes from latest 7-Zip for
Windows.
These two ports are not identical.
Note also that some Linux specific things can be implemented better in p7zip than in new 7-Zip for
Linux.
There are several main executables in 7-Zip and p7zip:
7zz (7-Zip) - standalone full version of 7-Zip that supports all formats.
7zzs (7-Zip) - standalone full version of 7-Zip that supports all formats (static library
linking).
7z (p7zip) - 7-Zip that requires 7z.so shared library, and it supports all formats via 7z.so.
7zr (p7zip) - standalone reduced version of 7-Zip that supports some 7-Zip's formats:
7z, xz, lzma and split.
7za (p7zip) - standalone version of 7-Zip that supports some main formats:
7z, xz, lzma, zip, bzip2, gzip, tar, cab, ppmd and split.
7zzs is similar to 7zz, but 7zzs was compiled for static library linking,
so 7zzs does not use external shared library (".so") files.
You can use 7zzs, if 7zz does not work due to lack of required shared library (".so") files.
The command line syntax for executables from p7zip is similar to 7zz syntax from this package.
This change also renames the package names for PackageKit integration. If a distro wants File-Roller to
suggest installing `p7zip`, point `7zip` packages listed in packages.match file to it.
Most package repositories that ship 7zz disable the RAR support by default (e.g. Debian, NixOS).
data/packages.match | 6 +--
src/fr-archive-libarchive.c | 8 +++-
src/fr-command-7z.c | 100 +++++++++++++++++++++++++++++++++++++++-----
src/fr-command-tar.c | 6 +--
4 files changed, 102 insertions(+), 18 deletions(-)
---
diff --git a/data/packages.match b/data/packages.match
index 68ce591f..80e1099f 100644
--- a/data/packages.match
+++ b/data/packages.match
@@ -1,4 +1,7 @@
[Package Matches]
+7zip=
+7zip-full=
+7zip-rar=
arj=
binutils=
brotli=
@@ -13,9 +16,6 @@ lzip=
lzma=
lzop=
ncompress=
-p7zip=
-p7zip-full=
-p7zip-rar=
rar=
rpm=
rzip=
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index bc601c07..e7b0cfe1 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -116,7 +116,9 @@ fr_archive_libarchive_get_capabilities (FrArchive *archive,
/* give priority to 7z* for 7z archives. */
if (strcmp (mime_type, "application/x-7z-compressed") == 0) {
- if (_g_program_is_available ("7za", check_command)
+ if (_g_program_is_available ("7zz", check_command)
+ || _g_program_is_available ("7zzs", check_command)
+ || _g_program_is_available ("7za", check_command)
|| _g_program_is_available ("7zr", check_command)
|| _g_program_is_available ("7z", check_command))
{
@@ -135,7 +137,9 @@ fr_archive_libarchive_get_capabilities (FrArchive *archive,
if ((strcmp (mime_type, "application/zip") == 0)
|| (strcmp (mime_type, "application/x-cbz") == 0))
{
- if (_g_program_is_available ("7z", check_command)) {
+ if (_g_program_is_available ("7zz", check_command)
+ || _g_program_is_available ("7zzs", check_command)
+ || _g_program_is_available ("7z", check_command)) {
return capabilities;
}
if (!_g_program_is_available ("unzip", check_command)) {
diff --git a/src/fr-command-7z.c b/src/fr-command-7z.c
index 4e48a400..f3ecd6e4 100644
--- a/src/fr-command-7z.c
+++ b/src/fr-command-7z.c
@@ -179,7 +179,15 @@ list__process_line (char *line,
static void
fr_command_7z_begin_command (FrCommand *comm)
{
- if (_g_program_is_in_path ("7z"))
+ // Modern 7-Zip by the original author.
+ // Statically linked from a binary distribution, almost guaranteed to work.
+ if (_g_program_is_in_path ("7zzs"))
+ fr_process_begin_command (comm->process, "7zzs");
+ // Dynamically linked from either binary or source distribution.
+ else if (_g_program_is_in_path ("7zz"))
+ fr_process_begin_command (comm->process, "7zz");
+ // Legacy p7zip project.
+ else if (_g_program_is_in_path ("7z"))
fr_process_begin_command (comm->process, "7z");
else if (_g_program_is_in_path ("7za"))
fr_process_begin_command (comm->process, "7za");
@@ -589,6 +597,59 @@ fr_command_7z_get_mime_types (FrArchive *archive)
}
+static gboolean
+check_info_subcommand_for_codec_support (char *program_name, char *codec_name) {
+ if (! _g_program_is_in_path (program_name)) {
+ return FALSE;
+ }
+
+ g_autofree gchar **standard_output = NULL;
+
+ gchar* argv[] = {
+ program_name,
+ "i"
+ };
+ if (!g_spawn_sync (
+ /* working_directory = */ NULL,
+ argv,
+ /* envp = */ NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
+ /* child_setup = */ NULL,
+ /* user_data = */ NULL,
+ standard_output,
+ /* standard_error = */ NULL,
+ /* wait_status = */ NULL,
+ /* error = */ NULL
+ )) {
+ return FALSE;
+ }
+
+ gchar *codecs = g_strrstr(*standard_output, "Codecs:");
+
+ if (codecs == NULL) {
+ return FALSE;
+ }
+
+ gchar *codec_found = g_strrstr(codecs, codec_name);
+
+ return codec_found != NULL;
+}
+
+
+static gboolean
+has_rar_support (gboolean check_command)
+{
+ /*
+ * Some 7-Zip distributions store RAR codec as a separate shared library and we can detect that.
+ * Most commonly, however, the programs link the codec statically so the only way to find out is to
query them.
+ */
+ return !check_command
+ || g_file_test ("/usr/lib/p7zip/Codecs/Rar.so", G_FILE_TEST_EXISTS)
+ || check_info_subcommand_for_codec_support ("7zzs", "Rar3")
+ || check_info_subcommand_for_codec_support ("7zz", "Rar3");
+}
+
+
static FrArchiveCap
fr_command_7z_get_capabilities (FrArchive *archive,
const char *mime_type,
@@ -597,27 +658,46 @@ fr_command_7z_get_capabilities (FrArchive *archive,
FrArchiveCap capabilities;
capabilities = FR_ARCHIVE_CAN_STORE_MANY_FILES;
- if (! _g_program_is_available ("7za", check_command) && ! _g_program_is_available ("7zr",
check_command) && ! _g_program_is_available ("7z", check_command))
+ /*
+ * We support two sets of program names:
+ * - 7z/7za/7zr from the no longer maintained p7zip project
+ * - 7zz/7zzs from the 7-Zip project by the original author
+ * Their CLI is mostly compatible.
+ */
+
+ // Support full range of formats (except possibly rar).
+ gboolean available_7zip = _g_program_is_available ("7zzs", check_command) || _g_program_is_available
("7zz", check_command);
+ gboolean available_p7zip_full = _g_program_is_available ("7z", check_command);
+ gboolean available_formats_full = available_7zip || available_p7zip_full;
+ // Supports 7z, xz, lzma, zip, bzip2, gzip, tar, cab, ppmd and split.
+ gboolean available_p7zip_partial = _g_program_is_available ("7za", check_command);
+ // Supports 7z, xz, lzma and split.
+ gboolean available_p7zip_reduced = _g_program_is_available ("7zr", check_command);
+
+ if (! available_7zip
+ && ! available_p7zip_full
+ && ! available_p7zip_partial
+ && ! available_p7zip_reduced)
return capabilities;
if (_g_mime_type_matches (mime_type, "application/x-7z-compressed")) {
capabilities |= FR_ARCHIVE_CAN_READ_WRITE | FR_ARCHIVE_CAN_CREATE_VOLUMES;
- if (_g_program_is_available ("7z", check_command))
+ if (available_formats_full)
capabilities |= FR_ARCHIVE_CAN_ENCRYPT | FR_ARCHIVE_CAN_ENCRYPT_HEADER;
}
else if (_g_mime_type_matches (mime_type, "application/x-7z-compressed-tar")) {
capabilities |= FR_ARCHIVE_CAN_READ_WRITE;
- if (_g_program_is_available ("7z", check_command))
+ if (available_formats_full)
capabilities |= FR_ARCHIVE_CAN_ENCRYPT | FR_ARCHIVE_CAN_ENCRYPT_HEADER;
}
- else if (_g_program_is_available ("7z", check_command)) {
+ else if (available_formats_full) {
if (_g_mime_type_matches (mime_type, "application/x-rar")
|| _g_mime_type_matches (mime_type, "application/x-cbr"))
{
/* give priority to rar and unrar that supports RAR files better. */
if (!_g_program_is_available ("rar", check_command)
&& !_g_program_is_available ("unrar", check_command)
- && (! check_command || g_file_test ("/usr/lib/p7zip/Codecs/Rar.so",
G_FILE_TEST_EXISTS)))
+ && has_rar_support (check_command))
capabilities |= FR_ARCHIVE_CAN_READ;
}
else
@@ -630,7 +710,7 @@ fr_command_7z_get_capabilities (FrArchive *archive,
capabilities |= FR_ARCHIVE_CAN_WRITE | FR_ARCHIVE_CAN_ENCRYPT;
}
}
- else if (_g_program_is_available ("7za", check_command)) {
+ else if (available_p7zip_partial) {
if (_g_mime_type_matches (mime_type, "application/vnd.ms-cab-compressed")
|| _g_mime_type_matches (mime_type, "application/zip"))
{
@@ -654,11 +734,11 @@ fr_command_7z_get_packages (FrArchive *archive,
const char *mime_type)
{
if (_g_mime_type_matches (mime_type, "application/x-rar"))
- return PACKAGES ("p7zip,p7zip-rar");
+ return PACKAGES ("7zip,7zip-rar");
else if (_g_mime_type_matches (mime_type, "application/zip") || _g_mime_type_matches (mime_type,
"application/vnd.ms-cab-compressed"))
- return PACKAGES ("p7zip,p7zip-full");
+ return PACKAGES ("7zip,7zip-full");
else
- return PACKAGES ("p7zip");
+ return PACKAGES ("7zip");
}
diff --git a/src/fr-command-tar.c b/src/fr-command-tar.c
index 3c620772..22eab489 100644
--- a/src/fr-command-tar.c
+++ b/src/fr-command-tar.c
@@ -1241,7 +1241,7 @@ fr_command_tar_get_capabilities (FrArchive *archive,
capabilities |= FR_ARCHIVE_CAN_READ_WRITE;
}
else if (_g_mime_type_matches (mime_type, "application/x-7z-compressed-tar")) {
- char *try_command[3] = { "7za", "7zr", "7z" };
+ char *try_command[5] = { "7zzs", "7zz", "7za", "7zr", "7z" };
int i;
for (i = 0; i < G_N_ELEMENTS (try_command); i++) {
@@ -1273,7 +1273,7 @@ fr_command_tar_set_mime_type (FrArchive *archive,
FR_ARCHIVE_CLASS (fr_command_tar_parent_class)->set_mime_type (archive, mime_type);
if (_g_mime_type_matches (mime_type, "application/x-7z-compressed-tar")) {
- char *try_command[3] = { "7za", "7zr", "7z" };
+ char *try_command[5] = { "7zzs", "7zz", "7za", "7zr", "7z" };
int i;
for (i = 0; i < G_N_ELEMENTS (try_command); i++) {
@@ -1313,7 +1313,7 @@ fr_command_tar_get_packages (FrArchive *archive,
else if (_g_mime_type_matches (mime_type, "application/x-tzo"))
return PACKAGES ("tar,lzop");
else if (_g_mime_type_matches (mime_type, "application/x-7z-compressed-tar"))
- return PACKAGES ("tar,p7zip");
+ return PACKAGES ("tar,7zip");
else if (_g_mime_type_matches (mime_type, "application/x-rzip-compressed-tar"))
return PACKAGES ("tar,rzip");
else if (_g_mime_type_matches (mime_type, "application/x-zstd-compressed-tar"))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]