Maintain file permissions when extracting from a zip file using JDK 5 api
Asked Answered
R

7

21

I am using java.util.Zip and java.util.ZipEntry to successfully extra a zip file's contents to disk. I would like to maintain the file permissions set when extracting on a *nix file-system.

Can anyone point me to the "correct" way to do this?

Rhinoplasty answered 26/6, 2009 at 18:32 Comment(3)
I know this is an rather old post but have you solved that issue ? I'm having the same problem right now ; It only seems to affect an executable file so far... when I unzip it "by hand" the permission is correctEnchilada
I have not in fact solved it. My last approach vector was going to be to pull apart apache's ant task for manipulating zip files and determine what they are doing.Rhinoplasty
Ant can do that only since 1.8, using the new feature of Java.io.File in java 6 (see my answer below)Enchilada
F
0

Essentially, you can't STORE (unix) file permissions in Zip/Jar files, so you can't preserve them when extracting your jar (they were lost when the jar was created to begin with). See this question: creating a jar file - preserving file permissions

If you need the file permissions preserved in the archive and restored when extracting, you need to consider the alternative .tar or .tar.gz / .tar.bz2 format, which is also natively supported by most Java build tools (Ant, Gradle, Maven...)

Forsythe answered 15/12, 2016 at 17:36 Comment(2)
This is not entirely accurate. Extra fields are commonly used for the purposes of file permission preservation.Insalubrious
Thank you @Cameron I do realize that this answer is no longer the most accurate, and even may not have been when written years ago. Still it's not a bad answer that deserves the -1's since then (not implying you did :-) ). It would be more helpful to the community to provide a newer answer that reflects the best answer to this question, today, if you can expand on your comment ? I'd happily upvote it and delete mine.Forsythe
E
10

I think it is actually impossible to keep the permissions correctly.

Permissions are very OS specific: while POSIX file permissions allow the user to set whether you can read, write or execute a file for the file owner, the group and others, the NTFS file system has a similar system but the concept for an execute permission is inexistant. And the early FAT/FAT32 file syste, do not have file permissions at all (a part from the read-only attribute).

Being cross-platform, it would be difficult for java to set the permission properly on the newly created (unzipped) files depending on the underlying OS....

That said, Java 6 has a new java.io.File class that allows you to set permissions (with methods like setExecutable(), setReadable(), etc...)

These helped me a lot, especially the setExecutable() which was my main concerned when having to unzip executables on a Linux file system. And you don't have to bother about figuring out what OS you are running on as the method will simply do nothing if running under Windows or other systems without the concept of executable files.

Enchilada answered 12/3, 2010 at 11:54 Comment(1)
I know this thread is getting quite old but your answer helped me. I was trying to extract a ***.app on Mac Os but the resulting application would launch, I changed permissions of the actual launcher file inside it using the setExecutable() method and it seems to be working perfectly ! Thanks for the help :)Sinhalese
V
5

The unix permissions are stored in the zip, either in the entry external attributes, or in the extra fields (using the "Asi" extra field, tagged with the 0x756E id). java.util.zip.ZipEntry exposes the extra fields and the Asi field could be read if there is one, but the external attributes are not accessible. So it's not possible to restore the files permissions in all cases using only the JDK zip implementation.

Fortunately the Apache Commons Compress project has its own ZipFile implementation which parses the external attributes, the permissions are exposed with the ZipArchiveEntry.getUnixMode() method. Then with Ant's PermissionUtils class and the Java NIO API, the permissions can be applied back to the file extracted with:

Files.setPosixFilePermissions(path, PermissionUtils.permissionsFromMode(entry.getUnixMode()));
Viveca answered 2/4, 2021 at 10:4 Comment(0)
C
1

Look at Apache Commons Compress and look at TarArchiveEntry, that should preserve the file permissions like you want it to.

TarArchiveEntry entry = tarInput.getNextTarEntry();

Here are the javadocs. I think I've gone Commons mad...

Canto answered 26/6, 2009 at 18:53 Comment(3)
does TarArchiveEntry work on zips as well as tar files? they are not the same, right?Susiesuslik
I agree with Cheeso - what does this have to do with zip files ?Enchilada
There is also ZipArchiveEntry commons.apache.org/proper/commons-compress/zip.htmlRustic
N
1

As tracked in this OpenJDK bug: https://bugs.openjdk.java.net/browse/JDK-6194856:

The "standard" zip file format does not have any way to store "executable file" meta-information, since it was originally designed for MS-DOS filesystems.

In order to preserve Unix information like file modes, the zip handling code would have to handle extensions to the zip file format. Other zip implementations have such extensions.

There are some extensions to the file format that would allow maintaining this kind of information, but it can never be guaranteed (there is no requirement that zip files contain such "extended" metadata) and it would be a lot of work to implement and (especially!) test.

Also see this answer: Can i store unix permissions in a zip file (built with apache ant)?

Non-standard Java libraries may implement this (such as apache-commons).

Nectar answered 22/2, 2019 at 3:29 Comment(0)
F
0

Essentially, you can't STORE (unix) file permissions in Zip/Jar files, so you can't preserve them when extracting your jar (they were lost when the jar was created to begin with). See this question: creating a jar file - preserving file permissions

If you need the file permissions preserved in the archive and restored when extracting, you need to consider the alternative .tar or .tar.gz / .tar.bz2 format, which is also natively supported by most Java build tools (Ant, Gradle, Maven...)

Forsythe answered 15/12, 2016 at 17:36 Comment(2)
This is not entirely accurate. Extra fields are commonly used for the purposes of file permission preservation.Insalubrious
Thank you @Cameron I do realize that this answer is no longer the most accurate, and even may not have been when written years ago. Still it's not a bad answer that deserves the -1's since then (not implying you did :-) ). It would be more helpful to the community to provide a newer answer that reflects the best answer to this question, today, if you can expand on your comment ? I'd happily upvote it and delete mine.Forsythe
W
0

I actually sat there looking over these answers and was stuck with this issue but then I realized I was doing something rather silly.

I was extracting to a temp folder, then using FileUtils.copyDirectory to copy the files from the temp folder to the new folder.

Instead of doing a copy, I changed to a move operation. now it worked.

I can confirm, on Ubuntu Linux 22.04, this maintains file permissions.

Uses: implementation group: 'org.rauschig', name: 'jarchivelib', version: '1.2.0'

import org.rauschig.jarchivelib.ArchiveFormat;
import org.rauschig.jarchivelib.Archiver;
import org.rauschig.jarchivelib.ArchiverFactory;
import org.rauschig.jarchivelib.CompressionType;

  public static void unzip(File zipFile, File targetDirectory) throws IOException, IllegalAccessException {
    Archiver archiver = ArchiverFactory.createArchiver(ArchiveFormat.ZIP);
    archiver.extract(zipFile, targetDirectory);
  }

  public static void unTarGz(File tarFile, File targetDirectory) throws IOException {
    Archiver archiver = ArchiverFactory.createArchiver(ArchiveFormat.TAR, CompressionType.GZIP);
    archiver.extract(tarFile, targetDirectory);
  }
Woodham answered 19/4, 2022 at 1:14 Comment(0)
O
0

If you use Apache Commons Compress , you can set the readonly flag using the external attributes.

The flag will be preserved after extraction in windows.

zipEntry.setVersionMadeBy(0x0000); // 00 is for MSDOS/Windows
zipEntry.setExternalAttributes(zipEntry.getExternalAttributes() | 0x00000001L); // First bit = 1 -> Readonly flag in windows

for more information please refer to the ZIP format spec. https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT

Overload answered 14/8, 2023 at 22:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.