Search in sources :

Example 1 with BundleEntry

use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.

the class BundleReader method read.

public Bundle read() throws BundleException, IOException {
    bundle = new Bundle();
    in.position(0);
    BundleHeader header = bundle.header();
    in.readStruct(header);
    // check signature
    if (!header.hasValidSignature()) {
        throw new BundleException("Invalid signature");
    }
    List<BundleEntryInfo> entryInfos = bundle.entryInfos();
    if (header.compressedDataHeaderSize() > 0) {
        if (header.dataHeaderAtEndOfFile()) {
            in.position(header.completeFileSize() - header.compressedDataHeaderSize());
        }
        // build an input stream for the uncompressed data header
        InputStream headerIn = new BoundedInputStream(in.stream(), header.compressedDataHeaderSize());
        DataReader inData;
        switch(header.dataHeaderCompressionScheme()) {
            default:
            case 0:
                // Not compressed
                inData = DataReaders.forInputStream(headerIn);
            case 1:
                // LZMA
                inData = DataReaders.forInputStream(new CountingInputStream(new LzmaInputStream(headerIn)));
            case 3:
                // LZ4
                byte[] compressed = new byte[header.compressedDataHeaderSize()];
                byte[] decompressed = new byte[(int) header.dataHeaderSize()];
                headerIn.read(compressed);
                LZ4JavaSafeFastDecompressor.INSTANCE.decompress(compressed, decompressed);
                inData = DataReaders.forByteBuffer(ByteBuffer.wrap(decompressed));
        }
        // Block info: not captured for now
        {
            // 16 bytes unknown
            byte[] unknown = new byte[16];
            inData.readBytes(unknown);
            int storageBlocks = inData.readInt();
            for (int i = 0; i < storageBlocks; ++i) {
                inData.readUnsignedInt();
                inData.readUnsignedInt();
                inData.readUnsignedShort();
            }
        }
        int files = inData.readInt();
        for (int i = 0; i < files; i++) {
            BundleEntryInfo entryInfo = new BundleEntryInfoFS();
            inData.readStruct(entryInfo);
            entryInfos.add(entryInfo);
        }
    } else {
        // raw or web header
        long dataHeaderSize = header.dataHeaderSize();
        if (dataHeaderSize == 0) {
            // old stream versions don't store the data header size, so use a large
            // fixed number instead
            dataHeaderSize = 4096;
        }
        InputStream is = dataInputStream(0, dataHeaderSize);
        DataReader inData = DataReaders.forInputStream(is);
        int files = inData.readInt();
        for (int i = 0; i < files; i++) {
            BundleEntryInfo entryInfo = new BundleEntryInfo();
            inData.readStruct(entryInfo);
            entryInfos.add(entryInfo);
        }
    }
    // sort entries by offset so that they're in the order in which they
    // appear in the file, which is convenient for compressed bundles
    entryInfos.sort((a, b) -> Long.compare(a.offset(), b.offset()));
    List<BundleEntry> entries = bundle.entries();
    entryInfos.forEach(entryInfo -> {
        entries.add(new BundleInternalEntry(entryInfo, this::inputStreamForEntry));
    });
    return bundle;
}
Also used : LzmaInputStream(net.contrapunctus.lzma.LzmaInputStream) BoundedInputStream(org.apache.commons.io.input.BoundedInputStream) CountingInputStream(org.apache.commons.io.input.CountingInputStream) InputStream(java.io.InputStream) CountingInputStream(org.apache.commons.io.input.CountingInputStream) DataReader(info.ata4.io.DataReader) LzmaInputStream(net.contrapunctus.lzma.LzmaInputStream) BoundedInputStream(org.apache.commons.io.input.BoundedInputStream)

Example 2 with BundleEntry

use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.

the class BundleUtils method byteChannelForEntry.

public static SeekableByteChannel byteChannelForEntry(BundleEntry entry) throws IOException {
    SeekableByteChannel chan;
    // check if the entry is larger than 128 MiB
    long size = entry.size();
    if (size > 1 << 27) {
        // copy entry to temporary file
        Path tmpFile = Files.createTempFile("disunity", null);
        Files.copy(entry.inputStream(), tmpFile, REPLACE_EXISTING);
        chan = Files.newByteChannel(tmpFile, READ, DELETE_ON_CLOSE);
    } else {
        // copy entry to memory
        ByteBuffer bb = ByteBuffer.allocateDirect((int) size);
        IOUtils.copy(entry.inputStream(), new ByteBufferOutputStream(bb));
        bb.flip();
        chan = new ByteBufferChannel(bb);
    }
    return chan;
}
Also used : SeekableByteChannel(java.nio.channels.SeekableByteChannel) Path(java.nio.file.Path) ByteBufferOutputStream(info.ata4.io.buffer.ByteBufferOutputStream) ByteBufferChannel(info.ata4.io.buffer.ByteBufferChannel) ByteBuffer(java.nio.ByteBuffer)

Example 3 with BundleEntry

use of info.ata4.junity.bundle.BundleEntry in project disunity by ata4.

the class AssetCommand method runFileRecursive.

@Override
protected void runFileRecursive(Path file) {
    if (BundleUtils.isBundle(file)) {
        // file is a bundle, load serialized files from it
        try (BundleReader bundleReader = new BundleReader(file)) {
            Bundle bundle = bundleReader.read();
            bundle.entries().stream().filter(not(BundleEntry::isLibrary)).filter(not(BundleEntry::isResource)).forEach(uncheck(entry -> {
                try (SerializedFileReader reader = new SerializedFileReader(BundleUtils.dataReaderForEntry(entry))) {
                    SerializedFile serialized = reader.read();
                    runSerializedFile(file.resolve(entry.name()), serialized);
                }
            }));
        } catch (UncheckedIOException | IOException ex) {
            L.log(Level.WARNING, "Can't open asset bundle " + file, ex);
        }
    } else {
        // load file directly
        try (SerializedFileReader reader = new SerializedFileReader(file)) {
            SerializedFile serialized = reader.read();
            runSerializedFile(file, serialized);
        } catch (IOException ex) {
            L.log(Level.WARNING, "Can't open asset file " + file, ex);
        }
    }
}
Also used : RecursiveFileCommand(info.ata4.disunity.cli.command.RecursiveFileCommand) LogUtils(info.ata4.log.LogUtils) IOConsumer.uncheck(info.ata4.util.function.IOConsumer.uncheck) IOException(java.io.IOException) Logger(java.util.logging.Logger) BundleUtils(info.ata4.junity.bundle.BundleUtils) SerializedFile(info.ata4.junity.serialize.SerializedFile) Predicates.not(info.ata4.util.function.Predicates.not) Level(java.util.logging.Level) BundleEntry(info.ata4.junity.bundle.BundleEntry) UncheckedIOException(java.io.UncheckedIOException) Bundle(info.ata4.junity.bundle.Bundle) SerializedFileReader(info.ata4.junity.serialize.SerializedFileReader) BundleReader(info.ata4.junity.bundle.BundleReader) Path(java.nio.file.Path) SerializedFileReader(info.ata4.junity.serialize.SerializedFileReader) SerializedFile(info.ata4.junity.serialize.SerializedFile) Bundle(info.ata4.junity.bundle.Bundle) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) BundleEntry(info.ata4.junity.bundle.BundleEntry) BundleReader(info.ata4.junity.bundle.BundleReader)

Aggregations

Path (java.nio.file.Path)2 RecursiveFileCommand (info.ata4.disunity.cli.command.RecursiveFileCommand)1 DataReader (info.ata4.io.DataReader)1 ByteBufferChannel (info.ata4.io.buffer.ByteBufferChannel)1 ByteBufferOutputStream (info.ata4.io.buffer.ByteBufferOutputStream)1 Bundle (info.ata4.junity.bundle.Bundle)1 BundleEntry (info.ata4.junity.bundle.BundleEntry)1 BundleReader (info.ata4.junity.bundle.BundleReader)1 BundleUtils (info.ata4.junity.bundle.BundleUtils)1 SerializedFile (info.ata4.junity.serialize.SerializedFile)1 SerializedFileReader (info.ata4.junity.serialize.SerializedFileReader)1 LogUtils (info.ata4.log.LogUtils)1 IOConsumer.uncheck (info.ata4.util.function.IOConsumer.uncheck)1 Predicates.not (info.ata4.util.function.Predicates.not)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 UncheckedIOException (java.io.UncheckedIOException)1 ByteBuffer (java.nio.ByteBuffer)1 SeekableByteChannel (java.nio.channels.SeekableByteChannel)1 Level (java.util.logging.Level)1