public static void WriteDebPackage( List <ArchiveEntry> archiveEntries, Stream tarXzStream, Stream targetStream, DebPackage pkg) { ArFileCreator.WriteMagic(targetStream); ArFileCreator.WriteEntry(targetStream, "debian-binary", ArFileMode, pkg.PackageFormatVersion + "\n"); WriteControl(targetStream, pkg, archiveEntries); ArFileCreator.WriteEntry(targetStream, "data.tar.xz", ArFileMode, tarXzStream); }
public void WriteTest() { using (Stream original = File.OpenRead("Deb/libplist3_1.12-3.1_amd64.deb")) using (Stream expected = File.OpenRead("Deb/libplist3_1.12-3.1_amd64.deb")) using (Stream actual = new MemoryStream()) using (Stream output = new ValidatingCompositeStream(null, actual, expected)) { ArFileCreator.WriteMagic(output); var input = new ArFile(original, true); while (input.Read()) { var header = (ArHeader)input.FileHeader; var clone = this.CloneHeader(header); this.AssertCompareClonedHeader(header, clone); using (var data = input.Open()) { ArFileCreator.WriteEntry(output, clone, data); } } } }
private static void WriteControl(Stream targetStream, DebPackage pkg, List <ArchiveEntry> entries) { var controlTar = new MemoryStream(); WriteControlEntry(controlTar, "./"); WriteControlEntry( controlTar, "./control", string.Join("\n", pkg.ControlFile .OrderByDescending(x => x.Key == "Package").ThenBy(x => x.Key) .Select(x => $"{x.Key}: {x.Value}")) + "\n"); WriteControlEntry( controlTar, "./md5sums", string.Join("\n", pkg.Md5Sums.Select(x => $"{x.Value} {x.Key}")) + "\n"); var execMode = LinuxFileMode.S_IRUSR | LinuxFileMode.S_IWUSR | LinuxFileMode.S_IXUSR | LinuxFileMode.S_IRGRP | LinuxFileMode.S_IROTH; if (!string.IsNullOrWhiteSpace(pkg.PreInstallScript)) { WriteControlEntry(controlTar, "./preinst", $"#!/bin/sh\n{pkg.PreInstallScript}\n", execMode); } if (!string.IsNullOrWhiteSpace(pkg.PostInstallScript)) { WriteControlEntry(controlTar, "./postinst", $"#!/bin/sh\n{pkg.PostInstallScript}\n", execMode); } if (!string.IsNullOrWhiteSpace(pkg.PreRemoveScript)) { WriteControlEntry(controlTar, "./prerm", $"#!/bin/sh\n{pkg.PreRemoveScript}\n", execMode); } if (!string.IsNullOrWhiteSpace(pkg.PostRemoveScript)) { WriteControlEntry(controlTar, "./postrm", $"#!/bin/sh\n{pkg.PostRemoveScript}\n", execMode); } var confFiles = entries .Where(e => e.Mode.HasFlag(LinuxFileMode.S_IFREG) && e.TargetPath.StartsWith("/etc/")) .Select(e => e.TargetPath).ToList(); if (confFiles.Any()) { WriteControlEntry(controlTar, "./conffiles", string.Join("\n", confFiles) + "\n"); } TarFileCreator.WriteTrailer(controlTar); controlTar.Seek(0, SeekOrigin.Begin); var controlTarGz = new MemoryStream(); using (var gzStream = new GZipStream(controlTarGz, CompressionMode.Compress, true)) { controlTar.CopyTo(gzStream); } controlTarGz.Seek(0, SeekOrigin.Begin); ArFileCreator.WriteEntry(targetStream, "control.tar.gz", ArFileMode, controlTarGz); }
public static void BuildDebPackage( List <ArchiveEntry> archiveEntries, Stream tarXzStream, string name, string description, string maintainer, string version, string arch, bool createUser, string userName, bool installService, string serviceName, string prefix, string section, string priority, string homepage, IEnumerable <string> additionalDependencies, Action <DebPackage> additionalMetadata, Stream targetStream) { var pkg = new DebPackage { Md5Sums = archiveEntries.Where(e => e.Md5Hash != null) .ToDictionary( e => e.TargetPath.TrimStart('.', '/'), e => BitConverter.ToString(e.Md5Hash).ToLower().Replace("-", string.Empty)), PackageFormatVersion = new Version(2, 0), ControlFile = new Dictionary <string, string> { ["Package"] = name, ["Version"] = version, ["Architecture"] = arch, ["Maintainer"] = maintainer, ["Description"] = description, ["Installed-Size"] = (archiveEntries.Sum(e => e.FileSize) / 1024).ToString() } }; if (!string.IsNullOrEmpty(section)) { pkg.ControlFile["Section"] = section; } if (!string.IsNullOrEmpty(priority)) { pkg.ControlFile["Priority"] = priority; } if (!string.IsNullOrEmpty(homepage)) { pkg.ControlFile["Homepage"] = homepage; } if (createUser) { // Add the user and group, under which the service runs. // These users are never removed because UIDs are re-used on Linux. pkg.PreInstallScript += $"/usr/sbin/groupadd -r {userName} 2>/dev/null || :\n" + $"/usr/sbin/useradd -g {userName} -s /sbin/nologin -r -d {prefix} {userName} 2>/dev/null || :\n"; } if (installService) { // Install and activate the service. pkg.PostInstallScript += $"systemctl reload"; pkg.PostInstallScript += $"systemctl enable --now {serviceName}.service"; pkg.PreRemoveScript += $"systemctl --no-reload disable --now {serviceName}.service"; } // Remove all directories marked as such (these are usually directories which contain temporary files) foreach (var entryToRemove in archiveEntries.Where(e => e.RemoveOnUninstall)) { pkg.PostRemoveScript += $"/usr/bin/rm -rf {entryToRemove.TargetPath}\n"; } pkg.ControlFile["Depends"] = string.Join(",", additionalDependencies); additionalMetadata?.Invoke(pkg); ArFileCreator.WriteMagic(targetStream); ArFileCreator.WriteEntry(targetStream, "debian-binary", ArFileMode, pkg.PackageFormatVersion + "\n"); WriteControl(targetStream, pkg, archiveEntries); ArFileCreator.WriteEntry(targetStream, "data.tar.xz", ArFileMode, tarXzStream); }
public static void BuildDebPackage( List <ArchiveEntry> archiveEntries, Stream tarXzStream, string name, string description, string maintainer, string version, string arch, bool createUser, string userName, bool installService, string serviceName, string prefix, IEnumerable <PackageDependency> additionalDependencies, Action <DebPackage> additionalMetadata, Stream targetStream) { var pkg = new DebPackage { Md5Sums = archiveEntries.Where(e => e.Md5Hash != null) .ToDictionary( e => e.TargetPath.TrimStart('.', '/'), e => BitConverter.ToString(e.Md5Hash).ToLower().Replace("-", string.Empty)), PackageFormatVersion = new Version(2, 0), ControlFile = new Dictionary <string, string> { ["Package"] = name, ["Version"] = version, ["Architecture"] = arch, ["Maintainer"] = maintainer, ["Description"] = description } }; if (createUser) { // Add the user and group, under which the service runs. // These users are never removed because UIDs are re-used on Linux. pkg.PreInstallScript += $"/usr/sbin/groupadd -r {userName} 2>/dev/null || :\n" + $"/usr/sbin/useradd -g {userName} -s /sbin/nologin -r -d {prefix} {userName} 2>/dev/null || :\n"; } if (installService) { // Install and activate the service. pkg.PostInstallScript += $"systemctl reload"; pkg.PostInstallScript += $"systemctl enable --now {serviceName}.service"; pkg.PreRemoveScript += $"systemctl --no-reload disable --now {serviceName}.service"; } // Remove all directories marked as such (these are usually directories which contain temporary files) foreach (var entryToRemove in archiveEntries.Where(e => e.RemoveOnUninstall)) { pkg.PostRemoveScript += $"/usr/bin/rm -rf {entryToRemove.TargetPath}\n"; } // Dependency list from https://github.com/dotnet/dotnet-docker/blob/master/2.0/runtime-deps/jessie/amd64/Dockerfile string libicu = string.Join(" | ", Enumerable.Range(40, 60).Select(n => "libicu" + n)); string deps = "libc6, libcurl3, libgcc1, libgssapi-krb5-2, liblttng-ust0, libssl1.0.0, libstdc++6, libunwind8, libuuid1, zlib1g, " + libicu; if (additionalDependencies != null) { foreach (var dependency in additionalDependencies) { deps += ", " + dependency; } } pkg.ControlFile["Depends"] = deps; additionalMetadata?.Invoke(pkg); ArFileCreator.WriteMagic(targetStream); ArFileCreator.WriteEntry(targetStream, "debian-binary", ArFileMode, pkg.PackageFormatVersion + "\n"); WriteControl(targetStream, pkg, archiveEntries); ArFileCreator.WriteEntry(targetStream, "data.tar.xz", ArFileMode, tarXzStream); }