Skip to content

Commit

Permalink
I have written a Java command line tool to unpack ".pack.xz" archives…
Browse files Browse the repository at this point in the history
…. It is based on the code of the Forge Installer.
  • Loading branch information
JBou committed Mar 27, 2014
1 parent a4aac78 commit 47d5ccd
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Pack.xzExtractor/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/xz-1.5.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
11 changes: 11 additions & 0 deletions Pack.xzExtractor/.externalToolBuilders/Jar_Builder.launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value=""/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Pack.xzExtractor/bin/build.xml}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>
27 changes: 27 additions & 0 deletions Pack.xzExtractor/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Pack.xzExtractor</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/Jar_Builder.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
11 changes: 11 additions & 0 deletions Pack.xzExtractor/.settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
Binary file added Pack.xzExtractor/lib/xz-1.5.jar
Binary file not shown.
93 changes: 93 additions & 0 deletions Pack.xzExtractor/src/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import org.tukaani.xz.XZInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;

public class Main {

public static void main(String[] args) throws IOException {
if (args.length > 2) {
System.out.println("Too many Arguments");
} else if (args.length < 2) {
System.out.println("Too little Arguments");
} else if (!new File(args[0]).exists()) {
System.out.println("InputFile does not exist");
} else {
try {
File input = new File(args[0]);
File output = new File(args[1]);
Path path = Paths.get(input.getAbsolutePath());
byte[] data = Files.readAllBytes(path);
unpackLibrary(output, data);
//success
System.exit(0);
} catch (Exception e) {
System.out.println("Error unpacking File: " + e.getLocalizedMessage());
//error
System.exit(1);
}
}
}

public static void unpackLibrary(File output, byte[] data)
throws IOException {
if (output.exists()) {
output.delete();
}

byte[] decompressed = readFully(new XZInputStream(
new ByteArrayInputStream(data)));

// Snag the checksum signature
String end = new String(decompressed, decompressed.length - 4, 4);
if (!end.equals("SIGN")) {
System.out.println("Unpacking failed, signature missing " + end);
return;
}

int x = decompressed.length;
int len = ((decompressed[x - 8] & 0xFF))
| ((decompressed[x - 7] & 0xFF) << 8)
| ((decompressed[x - 6] & 0xFF) << 16)
| ((decompressed[x - 5] & 0xFF) << 24);
byte[] checksums = Arrays.copyOfRange(decompressed, decompressed.length
- len - 8, decompressed.length - 8);

FileOutputStream jarBytes = new FileOutputStream(output);
JarOutputStream jos = new JarOutputStream(jarBytes);
Pack200.newUnpacker().unpack(new ByteArrayInputStream(decompressed),
jos);

jos.putNextEntry(new JarEntry("checksums.sha1"));
jos.write(checksums);
jos.closeEntry();

jos.close();
jarBytes.close();
}

public static byte[] readFully(InputStream stream) throws IOException {
byte[] data = new byte[4096];
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
int len;
do {
len = stream.read(data);
if (len > 0) {
entryBuffer.write(data, 0, len);
}
} while (len != -1);

return entryBuffer.toByteArray();
}

}
14 changes: 14 additions & 0 deletions Pack.xzExtractor/src/build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" ?>
<!-- Configuration of the Ant build system to generate a Jar file -->
<project name="Pack.xz_Extractor" default="CreateJar">
<property name="lib.dir" value="../lib"/>
<target name="CreateJar" description="Create Jar file">
<jar jarfile="Pack_xz_Extractor.jar" basedir=".">
<manifest>
<attribute name="Main-Class" value="Main" />
</manifest>
<zipgroupfileset dir="${lib.dir}" includes="**/*.jar" />
<fileset dir="../bin" includes="**/*.class" />
</jar>
</target>
</project>

0 comments on commit 47d5ccd

Please sign in to comment.