mass update
dependent modules: aosp update kotlin: 1.4.0 -> 1.4.10 unify helpers between projects commons.compress 1.20 bbootimage: fix page size error in vendor_boot supress compile warnings lz4: change lz4 compress parameter if lz4 is not up-to-date use external lz4 to decompress kernel for Ubuntu <=18.04 cpio: use java cpio to decompress ramdisk add skipcpio to read contatenate cpiofor/win
parent
fed5daeeba
commit
ddd1ad5ef2
@ -0,0 +1 @@
|
||||
https://github.com/dracutdevs/dracut/tree/master/skipcpio
|
@ -0,0 +1,122 @@
|
||||
/* dracut-install.c -- install files and executables
|
||||
|
||||
Copyright (C) 2012 Harald Hoyer
|
||||
Copyright (C) 2012 Red Hat, Inc. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define PROGRAM_VERSION_STRING "1"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CPIO_END "TRAILER!!!"
|
||||
#define CPIO_ENDLEN (sizeof(CPIO_END)-1)
|
||||
|
||||
static char buf[CPIO_ENDLEN * 2 + 1];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
size_t s;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
f = fopen(argv[1], "r");
|
||||
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
s = fread(buf, 6, 1, f);
|
||||
if (s <= 0) {
|
||||
fprintf(stderr, "Read error from file '%s'\n", argv[1]);
|
||||
fclose(f);
|
||||
exit(1);
|
||||
}
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
/* check, if this is a cpio archive */
|
||||
if (buf[0] == '0' && buf[1] == '7' && buf[2] == '0' && buf[3] == '7' && buf[4] == '0' && buf[5] == '1') {
|
||||
long pos = 0;
|
||||
|
||||
/* Search for CPIO_END */
|
||||
do {
|
||||
char *h;
|
||||
fseek(f, pos, SEEK_SET);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
s = fread(buf, CPIO_ENDLEN, 2, f);
|
||||
if (s <= 0)
|
||||
break;
|
||||
|
||||
h = strstr(buf, CPIO_END);
|
||||
if (h) {
|
||||
pos = (h - buf) + pos + CPIO_ENDLEN;
|
||||
fseek(f, pos, SEEK_SET);
|
||||
break;
|
||||
}
|
||||
pos += CPIO_ENDLEN;
|
||||
} while (!feof(f));
|
||||
|
||||
if (feof(f)) {
|
||||
/* CPIO_END not found, just cat the whole file */
|
||||
fseek(f, 0, SEEK_SET);
|
||||
} else {
|
||||
/* skip zeros */
|
||||
while (!feof(f)) {
|
||||
size_t i;
|
||||
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
s = fread(buf, 1, sizeof(buf) - 1, f);
|
||||
if (s <= 0)
|
||||
break;
|
||||
|
||||
for (i = 0; (i < s) && (buf[i] == 0); i++) ;
|
||||
|
||||
if (buf[i] != 0) {
|
||||
pos += i;
|
||||
fseek(f, pos, SEEK_SET);
|
||||
break;
|
||||
}
|
||||
|
||||
pos += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* cat out the rest */
|
||||
while (!feof(f)) {
|
||||
s = fread(buf, 1, sizeof(buf), f);
|
||||
if (s <= 0)
|
||||
break;
|
||||
|
||||
s = fwrite(buf, 1, s, stdout);
|
||||
if (s <= 0)
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -0,0 +1,416 @@
|
||||
package cfig.helper
|
||||
|
||||
import cfig.helper.Helper.Companion.check_call
|
||||
import cfig.helper.Helper.Companion.check_output
|
||||
import cfig.io.Struct3
|
||||
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream
|
||||
import org.apache.commons.compress.archivers.zip.*
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
||||
import org.apache.commons.compress.compressors.gzip.GzipParameters
|
||||
import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream
|
||||
import org.apache.commons.compress.utils.IOUtils
|
||||
import org.apache.commons.exec.CommandLine
|
||||
import org.apache.commons.exec.DefaultExecutor
|
||||
import org.apache.commons.exec.PumpStreamHandler
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.*
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.net.URI
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import java.util.zip.ZipException
|
||||
import kotlin.reflect.full.declaredFunctions
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
|
||||
class ZipHelper {
|
||||
class ZipEntryRecipe(val data: ByteArray, val name: String, val method: ZipMethod)
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger("ZipHelper")
|
||||
|
||||
fun unZipFile2(fileName: String, outDir: String) {
|
||||
val zis = ZipArchiveInputStream(BufferedInputStream(FileInputStream(fileName)))
|
||||
while (true) {
|
||||
val entry = zis.nextZipEntry ?: break
|
||||
val entryOut = File(outDir + "/" + entry.name)
|
||||
when {
|
||||
entry.isDirectory -> {
|
||||
log.error("Found dir : " + entry.name)
|
||||
throw IllegalArgumentException("this should not happen")
|
||||
}
|
||||
entry.isUnixSymlink -> {
|
||||
log.error("Found link: " + entry.name)
|
||||
throw IllegalArgumentException("this should not happen")
|
||||
}
|
||||
else -> {
|
||||
if (entry.name.contains("/")) {
|
||||
log.debug("Createing dir: " + entryOut.parentFile.canonicalPath)
|
||||
entryOut.parentFile.mkdirs()
|
||||
}
|
||||
log.info("Unzipping " + entry.name)
|
||||
IOUtils.copy(zis, FileOutputStream(entryOut))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
https://github.com/python/cpython/blob/3.8/Lib/zipfile.py
|
||||
The "local file header" structure, magic number, size, and indices
|
||||
(section V.A in the format document)
|
||||
structFileHeader = "<4s2B4HL2L2H"
|
||||
stringFileHeader = b"PK\003\004"
|
||||
sizeFileHeader = struct.calcsize(structFileHeader)
|
||||
*/
|
||||
fun ZipArchiveEntry.getEntryOffset(): Long {
|
||||
val zipFileHeaderSize = Struct3("<4s2B4HL2L2H").calcSize()
|
||||
val funGetLocalHeaderOffset = ZipArchiveEntry::class.declaredFunctions.filter { funcItem ->
|
||||
funcItem.name == "getLocalHeaderOffset"
|
||||
}[0]
|
||||
funGetLocalHeaderOffset.isAccessible = true
|
||||
val headerOffset = funGetLocalHeaderOffset.call(this) as Long
|
||||
val offset: Long = headerOffset + zipFileHeaderSize + this.localFileDataExtra.size + this.name.length
|
||||
log.debug("headerOffset = $headerOffset")
|
||||
log.debug("calcSize: $zipFileHeaderSize")
|
||||
return offset
|
||||
}
|
||||
|
||||
fun dumpZipEntry(inFile: String, entryName: String, outFile: String) {
|
||||
log.info("dumping: $inFile#$entryName -> $outFile")
|
||||
val zf = ZipFile(inFile)
|
||||
val entry = zf.getEntry(entryName)
|
||||
FileOutputStream(outFile).use { outStream ->
|
||||
zf.getInputStream(entry).copyTo(outStream)
|
||||
}
|
||||
zf.close()
|
||||
}
|
||||
|
||||
fun getEntryStream(zipFile: ZipFile, entryName: String): InputStream {
|
||||
return zipFile.getInputStream(zipFile.getEntry(entryName))
|
||||
}
|
||||
|
||||
fun ZipFile.dumpEntryIfExists(entryName: String, outFile: File) {
|
||||
val entry = this.getEntry(entryName)
|
||||
if (entry != null) {
|
||||
log.info("dumping entry: $entryName -> $outFile")
|
||||
FileOutputStream(outFile).use { outStream ->
|
||||
this.getInputStream(entry).copyTo(outStream)
|
||||
}
|
||||
} else {
|
||||
log.info("dumping entry: $entryName : entry not found, skip")
|
||||
}
|
||||
}
|
||||
|
||||
fun ZipFile.dumpEntry(entryName: String, outFile: File) {
|
||||
log.info("dumping entry: $entryName -> $outFile")
|
||||
val entry = this.getEntry(entryName)
|
||||
FileOutputStream(outFile).use { outStream ->
|
||||
this.getInputStream(entry).copyTo(outStream)
|
||||
}
|
||||
}
|
||||
|
||||
fun ZipFile.dumpEntry(entryName: String, outFile: String) {
|
||||
log.info("dumping entry: $entryName -> $outFile")
|
||||
val entry = this.getEntry(entryName)
|
||||
FileOutputStream(outFile).use { outStream ->
|
||||
this.getInputStream(entry).copyTo(outStream)
|
||||
}
|
||||
}
|
||||
|
||||
fun ZipArchiveOutputStream.packFile(inFile: File, entryName: String, zipMethod: ZipMethod = ZipMethod.DEFLATED) {
|
||||
log.info("packing $entryName($zipMethod) from file $inFile (size=${inFile.length()} ...")
|
||||
val entry = ZipArchiveEntry(inFile, entryName)
|
||||
entry.method = zipMethod.ordinal
|
||||
this.putArchiveEntry(entry)
|
||||
IOUtils.copy(Files.newInputStream(inFile.toPath()), this)
|
||||
this.closeArchiveEntry()
|
||||
}
|
||||
|
||||
fun ZipArchiveOutputStream.packEntry(inBuf: ByteArray, entryName: String, zipMethod: ZipMethod = ZipMethod.DEFLATED) {
|
||||
log.info("packing $entryName($zipMethod) from memory data (size=${inBuf.size}...")
|
||||
val entry = ZipArchiveEntry(entryName)
|
||||
entry.method = zipMethod.ordinal
|
||||
this.putArchiveEntry(entry)
|
||||
IOUtils.copy(ByteArrayInputStream(inBuf), this)
|
||||
this.closeArchiveEntry()
|
||||
}
|
||||
|
||||
fun ZipArchiveOutputStream.packStream(inStream: InputStream, entryName: String, zipMethod: ZipMethod = ZipMethod.DEFLATED) {
|
||||
log.info("packing $entryName($zipMethod) from input stream (size=unknown...")
|
||||
val entry = ZipArchiveEntry(entryName)
|
||||
entry.method = zipMethod.ordinal
|
||||
this.putArchiveEntry(entry)
|
||||
IOUtils.copy(inStream, this)
|
||||
this.closeArchiveEntry()
|
||||
}
|
||||
|
||||
fun zipDelete(zipFile: File, entryName: String) {
|
||||
val zipProperties = mutableMapOf("create" to "false")
|
||||
val zipURI = URI.create("jar:file:" + zipFile.canonicalPath)
|
||||
FileSystems.newFileSystem(zipURI, zipProperties).use { zipfs ->
|
||||
val entryPath = zipfs.getPath(entryName)
|
||||
log.info("deleting " + entryPath.toUri() + " from ZIP File ${zipFile.name}")
|
||||
Files.delete(entryPath)
|
||||
}
|
||||
}
|
||||
|
||||
fun zipClone(inFile: String, outFile: String) {
|
||||
ZipFile(inFile).use { zf ->
|
||||
val zaos = ZipArchiveOutputStream(FileOutputStream(outFile))
|
||||
val e = zf.entries
|
||||
while (e.hasMoreElements()) {
|
||||
val entry = e.nextElement()
|
||||
zaos.putArchiveEntry(entry)
|
||||
IOUtils.copy(zf.getInputStream(entry), zaos)
|
||||
zaos.closeArchiveEntry()
|
||||
}
|
||||
zaos.finish()
|
||||
zaos.close()
|
||||
}
|
||||
}
|
||||
|
||||
fun zipEdit(inFile: String, entryRecipe: ZipEntryRecipe) {
|
||||
val tmpFile = File.createTempFile("edit.", ".zip")
|
||||
log.info("transforming $inFile --> $tmpFile ...")
|
||||
ZipFile(inFile).use { zf ->
|
||||
val zaos = ZipArchiveOutputStream(tmpFile)
|
||||
val e = zf.entries
|
||||
if (zf.getEntry(entryRecipe.name) == null) {
|
||||
log.info("adding new entry [${entryRecipe.name}(${entryRecipe.method})] into [${tmpFile.canonicalPath}]")
|
||||
val entry = ZipArchiveEntry(entryRecipe.name)
|
||||
entry.method = entryRecipe.method.ordinal
|
||||
zaos.putArchiveEntry(entry)
|
||||
IOUtils.copy(ByteArrayInputStream(entryRecipe.data), zaos)
|
||||
}
|
||||
|
||||
while (e.hasMoreElements()) {
|
||||
val entry = e.nextElement()
|
||||
zaos.putArchiveEntry(entry)
|
||||
if (entry.name == entryRecipe.name) {
|
||||
log.info("modifying existent entry [${entryRecipe.name}(${entryRecipe.method})] into [${tmpFile.canonicalPath}]")
|
||||
IOUtils.copy(ByteArrayInputStream(entryRecipe.data), zaos)
|
||||
} else {
|
||||
log.debug("cloning entry ${entry.name} ...")
|
||||
IOUtils.copy(zf.getInputStream(entry), zaos)
|
||||
}
|
||||
zaos.closeArchiveEntry()
|
||||
}
|
||||
|
||||
zaos.finish()
|
||||
zaos.close()
|
||||
}
|
||||
log.info("transforming $inFile --> ${tmpFile.name} done")
|
||||
Files.move(tmpFile.toPath(), File(inFile).toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
log.info("renaming ${tmpFile.canonicalPath} --> $inFile done")
|
||||
}
|
||||
|
||||
fun isGZ(compressedFile: String): Boolean {
|
||||
return try {
|
||||
GZIPInputStream(FileInputStream(compressedFile)).use { }
|
||||
true
|
||||
} catch (e: ZipException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun isXZ(compressedFile: String): Boolean {
|
||||
return try {
|
||||
XZCompressorInputStream(FileInputStream(compressedFile)).use { }
|
||||
true
|
||||
} catch (e: ZipException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun isLZ4(compressedFile: String): Boolean {
|
||||
return try {
|
||||
"lz4 -t $compressedFile".check_call()
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun decompressLZ4Ext(lz4File: String, outFile: String) {
|
||||
"lz4 -d -fv $lz4File $outFile".check_call()
|
||||
}
|
||||
|
||||
fun compressLZ4(lz4File: String, inputStream: InputStream) {
|
||||
FileOutputStream(File(lz4File)).use { fos ->
|
||||
val baosE = ByteArrayOutputStream()
|
||||
DefaultExecutor().let { exec ->
|
||||
exec.streamHandler = PumpStreamHandler(fos, baosE, inputStream)
|
||||
val cmd = CommandLine.parse("lz4 -l -12")
|
||||
if ("lz4 --version".check_output().contains("r\\d+,".toRegex())) {
|
||||
log.warn("lz4 version obsolete, needs update")
|
||||
} else {
|
||||
cmd.addArgument("--favor-decSpeed")
|
||||
}
|
||||
log.info(cmd.toString())
|
||||
exec.execute(cmd)
|
||||
}
|
||||
baosE.toByteArray().let {
|
||||
if (it.isNotEmpty()) {
|
||||
log.warn(String(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun decompressLZ4(framedLz4: String, outFile: String) {
|
||||
FramedLZ4CompressorInputStream(
|
||||
Files.newInputStream(Paths.get(framedLz4))).use { zIn ->
|
||||
Files.newOutputStream(Paths.get(outFile)).use { out ->
|
||||
log.info("decompress lz4: $framedLz4 -> $outFile")
|
||||
val buffer = ByteArray(8192)
|
||||
var n: Int
|
||||
while (-1 != zIn.read(buffer).also { n = it }) {
|
||||
out.write(buffer, 0, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun gnuZipFile(compressedFile: String, decompressedFile: String) {
|
||||
val buffer = ByteArray(1024)
|
||||
FileOutputStream(compressedFile).use { fos ->
|
||||
GZIPOutputStream(fos).use { gos ->
|
||||
FileInputStream(decompressedFile).use { fis ->
|
||||
var bytesRead: Int
|
||||
while (true) {
|
||||
bytesRead = fis.read(buffer)
|
||||
if (bytesRead <= 0) break
|
||||
gos.write(buffer, 0, bytesRead)
|
||||
}
|
||||
gos.finish()
|
||||
log.info("gzip done: $decompressedFile -> $compressedFile")
|
||||
}//file-input-stream
|
||||
}//gzip-output-stream
|
||||
}//file-output-stream
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun unGnuzipFile(compressedFile: String, decompressedFile: String) {
|
||||
val buffer = ByteArray(1024)
|
||||
FileInputStream(compressedFile).use { fileIn ->
|
||||
//src
|
||||
GZIPInputStream(fileIn).use { gZIPInputStream ->
|
||||
//src
|
||||
FileOutputStream(decompressedFile).use { fileOutputStream ->
|
||||
var bytesRead: Int
|
||||
while (true) {
|
||||
bytesRead = gZIPInputStream.read(buffer)
|
||||
if (bytesRead <= 0) break
|
||||
fileOutputStream.write(buffer, 0, bytesRead)
|
||||
}
|
||||
log.info("decompress(gz) done: $compressedFile -> $decompressedFile")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
caution: about gzip header - OS (Operating System)
|
||||
|
||||
According to https://docs.oracle.com/javase/8/docs/api/java/util/zip/package-summary.html and
|
||||
GZIP spec RFC-1952(http://www.ietf.org/rfc/rfc1952.txt), gzip files created from java.util.zip.GZIPOutputStream
|
||||
will mark the OS field with
|
||||
0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
|
||||
But default image built from Android source code has the OS field:
|
||||
3 - Unix
|
||||
This MAY not be a problem, at least we didn't find it till now.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
@Deprecated("this function misses features")
|
||||
fun gnuZipFile(compressedFile: String, fis: InputStream) {
|
||||
val buffer = ByteArray(1024)
|
||||
FileOutputStream(compressedFile).use { fos ->
|
||||
GZIPOutputStream(fos).use { gos ->
|
||||
var bytesRead: Int
|
||||
while (true) {
|
||||
bytesRead = fis.read(buffer)
|
||||
if (bytesRead <= 0) break
|
||||
gos.write(buffer, 0, bytesRead)
|
||||
}
|
||||
log.info("compress(gz) done: $compressedFile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun gnuZipFile2(compressedFile: String, fis: InputStream) {
|
||||
val buffer = ByteArray(1024)
|
||||
val p = GzipParameters()
|
||||
p.operatingSystem = 3
|
||||
FileOutputStream(compressedFile).use { fos ->
|
||||
GzipCompressorOutputStream(fos, p).use { gos ->
|
||||
var bytesRead: Int
|
||||
while (true) {
|
||||
bytesRead = fis.read(buffer)
|
||||
if (bytesRead <= 0) break
|
||||
gos.write(buffer, 0, bytesRead)
|
||||
}
|
||||
log.info("compress(gz) done: $compressedFile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun decompressCPIO(cpioFile: String, outDir: String, fileList: String? = null) {
|
||||
run { //clean up
|
||||
if (File(outDir).exists()) {
|
||||
log.info("Cleaning $outDir ...")
|
||||
File(outDir).deleteRecursively()
|
||||
}
|
||||
File(outDir).mkdir()
|
||||
}
|
||||
val cis = CpioArchiveInputStream(FileInputStream(cpioFile))
|
||||
val fileListDump = if (fileList != null) FileOutputStream(fileList) else null
|
||||
|
||||
data class CpioEntryInfo(var type: String = "", var mode: String = "",
|
||||
var uid_gid: String = "", var name: String = "",
|
||||
var size: Long = 0, var linkTarget: String = "")
|
||||
while (true) {
|
||||
val entry = cis.nextCPIOEntry ?: break
|
||||
val entryInfo = CpioEntryInfo(name = entry.name,
|
||||
size = entry.size,
|
||||
mode = String.format("%6s", java.lang.Long.toOctalString(entry.mode)),
|
||||
uid_gid = "${entry.uid}/${entry.gid}")
|
||||
if (!cis.canReadEntryData(entry)) {
|
||||
throw RuntimeException("can not read entry ??")
|
||||
}
|
||||
val buffer = ByteArray(entry.size.toInt())
|
||||
cis.read(buffer)
|
||||
val outEntryName = File(outDir + "/" + entry.name).path
|
||||
when {
|
||||
entry.isRegularFile -> {
|
||||
entryInfo.type = "REG"
|
||||
File(outEntryName).writeBytes(buffer)
|
||||
Files.setPosixFilePermissions(Paths.get(outEntryName),
|
||||
Helper.modeToPermissions((entry.mode and 0xfff).toInt()))
|
||||
}
|
||||
entry.isSymbolicLink -> {
|
||||
entryInfo.type = "LNK"
|
||||
entryInfo.linkTarget = String(buffer)
|
||||
Files.createSymbolicLink(Paths.get(outEntryName), Paths.get(String(buffer)))
|
||||
}
|
||||
entry.isDirectory -> {
|
||||
entryInfo.type = "DIR"
|
||||
File(outEntryName).mkdir()
|
||||
Files.setPosixFilePermissions(Paths.get(outEntryName),
|
||||
Helper.modeToPermissions((entry.mode and 0xfff).toInt()))
|
||||
}
|
||||
else -> throw IllegalArgumentException("??? type unknown")
|
||||
}
|
||||
File(outEntryName).setLastModified(entry.time)
|
||||
log.debug(entryInfo.toString() + (", read " + cis.bytesRead))
|
||||
fileListDump?.write((entryInfo.toString() + ", read " + cis.bytesRead + "\n").toByteArray())
|
||||
}
|
||||
fileListDump?.close()
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 9aa59964ee1d0c828c8655ba7916f162c7721703
|
||||
Subproject commit de9ef14f57d6c39031710d015a4b3d13132bf5d7
|
Loading…
Reference in New Issue