From 652c68366f0245320f785524661a93c58bc39548 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 28 Sep 2023 11:56:20 +0200 Subject: [PATCH] Introduce Debian package support. --- .../src/org/argeo/slc/deb/DebFile.java | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 org.argeo.slc.cms/src/org/argeo/slc/deb/DebFile.java diff --git a/org.argeo.slc.cms/src/org/argeo/slc/deb/DebFile.java b/org.argeo.slc.cms/src/org/argeo/slc/deb/DebFile.java new file mode 100644 index 000000000..c51cea887 --- /dev/null +++ b/org.argeo.slc.cms/src/org/argeo/slc/deb/DebFile.java @@ -0,0 +1,136 @@ +package org.argeo.slc.deb; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.function.Consumer; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.ar.ArArchiveEntry; +import org.apache.commons.compress.archivers.ar.ArArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.CompressorException; +import org.apache.commons.compress.compressors.CompressorStreamFactory; + +public class DebFile { + private URL url; + + public DebFile(URL url) { + this.url = url; + } + + public void printDataArchive() { + openDataArchive((tarIn) -> { + try { + ArchiveEntry entry = null; + while ((entry = tarIn.getNextEntry()) != null) { + System.out.println(entry.getName()); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + public void printControlArchive() { + openControlArchive((tarIn) -> { + try { + ArchiveEntry entry = null; + while ((entry = tarIn.getNextEntry()) != null) { + System.out.println(entry.getName()); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + public void printControlFile() { + openControlArchive((tarIn) -> { + try { + ArchiveEntry entry = null; + while ((entry = tarIn.getNextEntry()) != null) { + if ("./control".equals(entry.getName())) { + String controlFileStr = new String(tarIn.readAllBytes(), StandardCharsets.UTF_8); + System.out.println(controlFileStr); + } + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + protected void openDataArchive(Consumer process) { + try (ArArchiveInputStream arIn = new ArArchiveInputStream(new BufferedInputStream(url.openStream()))) { + // order is specified, so we don't verify entry names + ArArchiveEntry debianBinaryEntry = arIn.getNextArEntry(); + assert "debian-binary".equals(debianBinaryEntry.getName()); + checkVersion(arIn); + arIn.getNextArEntry();// control archive + ArArchiveEntry dataArchiveEntry = arIn.getNextArEntry(); + processArArchiveEntry(dataArchiveEntry, arIn, process); + } catch (IOException | CompressorException e) { + throw new RuntimeException("Cannot open data archive of " + url, e); + } + } + + protected void openControlArchive(Consumer process) { + try (ArArchiveInputStream arIn = new ArArchiveInputStream(new BufferedInputStream(url.openStream()))) { + // order is specified, so we don't verify entry names + ArArchiveEntry debianBinaryEntry = arIn.getNextArEntry(); + assert "debian-binary".equals(debianBinaryEntry.getName()); + checkVersion(arIn); + ArArchiveEntry controlArchiveEntry = arIn.getNextArEntry(); + processArArchiveEntry(controlArchiveEntry, arIn, process); + } catch (IOException | CompressorException e) { + throw new RuntimeException("Cannot open control archive of " + url, e); + } + } + + protected void processArArchiveEntry(ArchiveEntry archiveEntry, ArArchiveInputStream arIn, + Consumer process) throws IOException, CompressorException { + String dataArchiveName = archiveEntry.getName(); + String compressionType = null; + if (dataArchiveName.endsWith(".xz")) + compressionType = CompressorStreamFactory.XZ; + else if (dataArchiveName.endsWith(".gz")) + compressionType = CompressorStreamFactory.GZIP; + else if (dataArchiveName.endsWith(".bzip2")) + compressionType = CompressorStreamFactory.BZIP2; + else if (dataArchiveName.endsWith(".lzma")) + compressionType = CompressorStreamFactory.LZMA; + + if (compressionType == null) { + try (TarArchiveInputStream tarIn = new TarArchiveInputStream(arIn)) { + process.accept(tarIn); + } + } else { + try (TarArchiveInputStream tarIn = new TarArchiveInputStream( + new CompressorStreamFactory().createCompressorInputStream(compressionType, arIn))) { + process.accept(tarIn); + } + } + } + + protected void checkVersion(ArArchiveInputStream arIn) throws IOException { + String version = new String(arIn.readAllBytes(), StandardCharsets.US_ASCII).trim(); + if (!"2.0".equals(version)) + throw new IllegalStateException("Deb " + version + " is not supported"); + } + + public static void main(String[] args) throws Exception { +// URL url = Paths +// .get(System.getProperty("user.home")+"/qa/git/argeo-qa-unstable/build/repo/deb/platform/2.3/argeo-cms_2.3.18_all.deb") +// .toUri().toURL(); + URL url = new URL("http://repo.netiket.eu/deb/pool/bullseye/platform/2.3/argeo-cms_2.3.18_all.deb"); + DebFile debFile = new DebFile(url); + debFile.printControlArchive(); + debFile.printControlFile(); + debFile.printDataArchive(); + } + +} -- 2.30.2