Bug 524702 - Regression: Ark commit 189f1f4e causes Drag-and-drop extraction with the libarchive plugin to silently omit empty directories
Summary: Regression: Ark commit 189f1f4e causes Drag-and-drop extraction with the lib...
Status: REPORTED
Alias: None
Product: ark
Classification: Applications
Component: plugins (other bugs)
Version First Reported In: 26.03.80
Platform: Fedora RPMs Linux
: NOR major
Target Milestone: ---
Assignee: Elvis Angelaccio
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-08-24 12:23 UTC by Tom Crider
Modified: 2026-09-26 00:56 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments
picture of archive contents vs. extraction result (81.34 KB, image/png)
2026-08-24 12:23 UTC, Tom Crider
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Crider 2026-08-24 12:23:20 UTC
Created attachment 195436 [details]
picture of archive contents vs. extraction result

Ark silently omits empty directories when a directory tree is dragged from the Ark GUI and dropped into a folder in Dolphin. This is a regression: `25.12.3` works, while `26.04.2`, `26.04.3`, and `26.08.0` reproduce the problem.

Normal full-archive extraction is not affected. The same archive extracts correctly using Ark's regular Extract/Extract All operation, `ark --batch`, `bsdtar`, or `tar`.

# Steps To Reproduce

1. Create a small archive containing both an empty and a non-empty directory:

   ```bash
   rm -rf /tmp/ark-dnd-source /tmp/ark-dnd-target
   mkdir -p /tmp/ark-dnd-source/root/empty
   mkdir -p /tmp/ark-dnd-source/root/nonempty
   printf 'test\n' > /tmp/ark-dnd-source/root/nonempty/file.txt
   tar -C /tmp/ark-dnd-source -czf /tmp/ark-dnd-empty-dir.tar.gz root
   mkdir -p /tmp/ark-dnd-target
   ```

2. Open `/tmp/ark-dnd-empty-dir.tar.gz` in Ark.
3. Drag the `root` directory from Ark's archive view and drop it into `/tmp/ark-dnd-target` in Dolphin.
4. Inspect the extracted tree:

   ```bash
   find /tmp/ark-dnd-target -print | sort
   ```

# Observed Result

`root/nonempty/file.txt` is extracted, and its parent directories are implicitly recreated, but `root/empty` is missing.

# Expected Result

The complete selected tree is extracted, including `root/empty`.

# Regression Range

- Last tested working version: Ark/ark-libs `25.12.3`
- First tested broken version: Ark/ark-libs `26.04.2`
- Also broken: `26.04.3` and `26.08.0`
- The regression is introduced by commit `189f1f4e411086d996d4e581c425a380d160b899` (included beginning with the `26.03.80` tag):
  <https://invent.kde.org/utilities/ark/-/commit/189f1f4e411086d996d4e581c425a380d160b899>

# Technical Analysis

Commit `189f1f4e411086d996d4e581c425a380d160b899` correctly normalizes libarchive directory entry names by removing trailing `/` characters before checking for existing destination files. However, partial extraction still builds `fullPaths` and `remainingFiles` with `ReadOnlyArchiveInterface::entryFullPaths()` using its default `WithTrailingSlash` format.

During drag-and-drop extraction Ark supplies an explicit selected-entry list. A selected directory is therefore stored as `root/empty/`, while the corresponding libarchive entry is normalized to `root/empty`. The membership test fails and Ark skips the directory entry. Parent directories for regular files are recreated as a side effect, which hides the problem for every directory except genuinely empty ones.

Full extraction passes an empty selected-entry list and uses the `extractAll` path, so it bypasses the mismatched membership test and works correctly.

# Proposed Fix

Normalize the two explicit selected-entry lists with the same representation used for libarchive entries:

```cpp
const QStringList fullPaths = entryFullPaths(files, NoTrailingSlash);
QStringList remainingFiles = entryFullPaths(files, NoTrailingSlash);
```

The attached patch also adds a regression test using the existing `empty_folders.tar.gz` fixture and drag-and-drop extraction options:

```
From 4cadf90043fbbe2c5bfc48355e2405b18f337811 Mon Sep 17 00:00:00 2001
From: GloriousEggroll <gloriouseggroll@gmail.com>
Date: Mon, 24 Aug 2026 06:04:05 -0600
Subject: [PATCH] libarchive: Preserve empty directories during partial
 extraction

Commit 189f1f4e411086d996d4e581c425a380d160b899 normalized libarchive directory entry names by removing trailing slashes. The explicit selected-entry lists retained their trailing slashes, so directory entries no longer matched during partial and drag-and-drop extraction. Non-empty parent directories were recreated while extracting files, but empty directories were silently omitted.

Normalize both selected-entry lists to the same no-trailing-slash representation and add coverage for drag-and-drop extraction of empty directories.

Fixes: 189f1f4e411086d996d4e581c425a380d160b899
---
 autotests/kerfuffle/extracttest.cpp     | 13 +++++++++++++
 plugins/libarchive/libarchiveplugin.cpp |  4 ++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/autotests/kerfuffle/extracttest.cpp b/autotests/kerfuffle/extracttest.cpp
index 8f9774fd..10721326 100644
--- a/autotests/kerfuffle/extracttest.cpp
+++ b/autotests/kerfuffle/extracttest.cpp
@@ -181,6 +181,19 @@ void ExtractTest::testExtraction_data()
     archivePath = QFINDTESTDATA("data/empty_folders.tar.gz");
     setupRow("tar with empty folders", archivePath, QList<Archive::Entry *>(), optionsPreservePaths, 5);
 
+    archivePath = QFINDTESTDATA("data/empty_folders.tar.gz");
+    setupRow("extract selected empty folders from a tar.gz, drag-and-drop",
+             archivePath,
+             QList<Archive::Entry *>{
+                 new Archive::Entry(this, QStringLiteral("A/"), QString()),
+                 new Archive::Entry(this, QStringLiteral("A/B/"), QString()),
+                 new Archive::Entry(this, QStringLiteral("A/B/test.txt"), QString()),
+                 new Archive::Entry(this, QStringLiteral("A/B/C/"), QString()),
+                 new Archive::Entry(this, QStringLiteral("A/B1/"), QString()),
+             },
+             dragAndDropOptions,
+             5);
+
     archivePath = QFINDTESTDATA("data/simplearchive.tar.bz2");
     setupRow("extract selected entries from a bzip2-compressed tarball without path",
              archivePath,
diff --git a/plugins/libarchive/libarchiveplugin.cpp b/plugins/libarchive/libarchiveplugin.cpp
index d625ea51..26e59bd7 100644
--- a/plugins/libarchive/libarchiveplugin.cpp
+++ b/plugins/libarchive/libarchiveplugin.cpp
@@ -293,8 +293,8 @@ bool LibarchivePlugin::extractFiles(const QList<Archive::Entry *> &files, const
     QString fileBeingRenamed;
     // To avoid traversing the entire archive when extracting a limited set of
     // entries, we maintain a list of remaining entries and stop when it's empty.
-    const QStringList fullPaths = entryFullPaths(files);
-    QStringList remainingFiles = entryFullPaths(files);
+    const QStringList fullPaths = entryFullPaths(files, NoTrailingSlash);
+    QStringList remainingFiles = entryFullPaths(files, NoTrailingSlash);
 
     // Iterate through all entries in archive.
     while (!QThread::currentThread()->isInterruptionRequested() && (archive_read_next_header(m_archiveReader.data(), &entry) == ARCHIVE_OK)) {
-- 
2.55.0
```

# System Information

- OS: Nobara Linux 44 KDE Plasma Edition
- Working Ark version currently installed: `25.12.3-1.fc44`
- Broken Ark versions tested: `26.04.2-1.fc43`, `26.04.3-1.fc44`, `26.08.0-1.fc44`
- libarchive: `3.8.7-1.fc44`
- KDE Plasma: `6.7.4-1.fc44`
- KDE Frameworks KArchive: `6.29.0-1.fc44`
- Qt: `6.11.1-1.fc44`

Extra:

I changed the severity to major as it effects basic user experience and can have severe trickle-down effects.

For example users manually installing custom proton versions for Steam will unknowingly end up with broken proton extractions and subsequently broken game launches. 

Specifically, the default_pfx folder in proton builds can break because it contains several empty directories that games/applications expect to exist in the prefix. Since proton copies default_pfx instead of using wineboot, those folders never get re-created:
Comment 1 Tarulia 2026-09-26 00:56:40 UTC
Just ran across this too and can confirm this on 26.08.1.

Full extraction (either via Dolphin's right-click -> extract, or Ark's extract menu) restores it, drag & drop does not.