Skip to content

#1884: keep symlinks while unzipping#1924

Merged
hohwille merged 6 commits into
devonfw:mainfrom
satorus:feature/1884-keep-symlinks-while-unzipping
May 21, 2026
Merged

#1884: keep symlinks while unzipping#1924
hohwille merged 6 commits into
devonfw:mainfrom
satorus:feature/1884-keep-symlinks-while-unzipping

Conversation

@satorus
Copy link
Copy Markdown
Contributor

@satorus satorus commented May 12, 2026

This PR fixes #1884

Implemented changes:

  • Rewrote extractZipWithJava to use ZipFile instead of Java FileSystem. This allows to read symlinks while also allowing to get the POSIX file permissions using File Attributes and Bit-Operations.
  • Two-phase symlink extraction: symlink entries are collected during extraction and created only after all regular files are written, matching the existing TAR behaviour.
  • Removed extractZipWithSystemUnzip: the Mac-specific workaround that used /usr/bin/unzip is gone. The Java implementation now handles all platforms uniformly.
  • Added getZipUnixMode and isZipSymlink helpers: isolate the bit-shifting logic for reading Unix file-type bits from ZIP external attributes, with full Javadoc explaining the bit layout.
  • Preserved file permissions via onFileCopiedFromZip using PathPermissions.of(unixMode).toPosix(), skipped on Windows.
  • 6 ZIP test resources added covering: basic symlink, reversed entry order, no Unix attributes (Windows ZIP), symlink + executable, symlink to directory, symlink with ../ relative target.
  • 12 new test cases in FileAccessImplTest covering: symlink preservation, file permissions, reversed entry order (validates two-phase approach), Windows-created ZIPs, combinations, directory symlinks, relative-parent symlinks, and OS-simulated permission behaviour (Mac and Windows mocks).

How to test:

Difficult. One test is to download and install Terraform and then running terraform --version. This shows that at least the file permissiosn still work. See: #835

For manually checking the unzipping, one can add (@TempDir(cleanup = CleanupMode.NEVER) Path tempDir) to the new test cases. This will create the ideasy-unzipped files in the /tmp/junit-... directories, where one can manually check the unzipped files for correct file permissions and existing symlinks.


Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summarizes what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labeled
    with internal

satorus added 3 commits May 12, 2026 09:20
…mlinks and keep existing symlinks in place
…missions + symlinks and for simulated mac and windows to check the isWindows() guard
@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board May 12, 2026
@satorus satorus added enhancement New feature or request unpack logic to unpack archives (tar, zip, tgz, zbz2, msi, dmg, etc.) labels May 12, 2026
@satorus satorus moved this from 🆕 New to Team Review in IDEasy board May 12, 2026
@satorus satorus marked this pull request as ready for review May 12, 2026 08:44
@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented May 12, 2026

Coverage Report for CI Build 26212181111

Coverage increased (+0.02%) to 70.996%

Details

  • Coverage increased (+0.02%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 197 coverage regressions across 2 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

197 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/io/FileAccessImpl.java 196 68.68%
com/devonfw/tools/ide/io/FileCopyMode.java 1 79.31%

Coverage Stats

Coverage Status
Relevant Lines: 15510
Covered Lines: 11484
Line Coverage: 74.04%
Relevant Branches: 6932
Covered Branches: 4449
Branch Coverage: 64.18%
Branches in Coverage %: Yes
Coverage Strength: 3.13 hits per line

💛 - Coveralls

@hohwille hohwille changed the title #1884 keep symlinks while unzipping #1884: keep symlinks while unzipping May 19, 2026
@hohwille
Copy link
Copy Markdown
Member

This PR looks really great. @satorus awesome that you researched deep and found the magic tricks. 👍
When I test this branch locally on Windows I get some test failures:

[ERROR] Errors:
[ERROR]   InstallCommandletTest.testInstallCommandletOfflineUpdateWithoutCachedDownload:287 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.6-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletOfflineWithCachedDownload:224 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.6-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletRunWithVersion:39 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-21.0.8_9-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletRunWithVersionAndVersionIdentifier:59 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.6-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletWithSkipUpdates:122 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.6-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletWithSkipUpdatesInstallsWhenNotInstalled:166 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.10-windows-x64.zip
[ERROR]   InstallCommandletTest.testInstallCommandletWithSkipUpdatesInstallsWhenVersionMismatch:187 » IllegalState Preventing path traversal attack from /bin/ to D:\bin leaving D:\projects\IDEasy\workspaces\main\IDEasy\cli\target\ide-projects\install\_ide\tmp\extract-java-17.0.6-windows-x64.zip
[INFO]
[ERROR] Tests run: 695, Failures: 0, Errors: 7, Skipped: 10

Copy link
Copy Markdown
Member

@hohwille hohwille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@satorus thanks for analysing and fixing this tricky issue.
Awesome that you also created various zip files with the different scenarios and covered everything perfectly with JUnit. Also your extensive JavaDoc is very helpful to understand this in the future. Great job.👍

@github-project-automation github-project-automation Bot moved this from Team Review to 👀 In review in IDEasy board May 21, 2026
@hohwille hohwille merged commit b77c017 into devonfw:main May 21, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from 👀 In review to ✅ Done in IDEasy board May 21, 2026
@hohwille
Copy link
Copy Markdown
Member

For retest and setting "QA approved" it would be awesome to also test #797 again with the latest SNAPSHOT on a Mac.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request unpack logic to unpack archives (tar, zip, tgz, zbz2, msi, dmg, etc.)

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Implement proper ZIP extraction

4 participants