internal static Stream GetPayloadStream(Stream stream) { using (ArFile archive = new ArFile(stream, leaveOpen: true)) { while (archive.Read()) { if (archive.FileName.StartsWith("data.tar.")) { var ext = Path.GetExtension(archive.FileName); if (ext == ".gz") { return(new GZipDecompressor(archive.Open(), false)); } if (ext == ".xz") { // For some reason it complains about corrupted data when we try to read using smaller chunks var payload = new MemoryStream(); using (var xz = new XZInputStream(archive.Open())) { xz.CopyTo(payload); payload.Seek(0, SeekOrigin.Begin); return(payload); } } throw new InvalidDataException("Don't know how to decompress " + archive.FileName); } } throw new InvalidDataException("data.tar.?? not found"); } }
public void ReadTarFileTest() { using (Stream stream = File.OpenRead("Deb/libplist3_1.12-3.1_amd64.deb")) using (ArFile arFile = new ArFile(stream, leaveOpen: true)) { // Skip the debian version arFile.Read(); // This is the tar file arFile.Read(); Collection <string> filenames = new Collection <string>(); Collection <string> contents = new Collection <string>(); Collection <TarHeader> headers = new Collection <TarHeader>(); using (Stream entryStream = arFile.Open()) using (GZipDecompressor decompressedStream = new GZipDecompressor(entryStream, leaveOpen: true)) using (TarFile tarFile = new TarFile(decompressedStream, leaveOpen: true)) { while (tarFile.Read()) { filenames.Add(tarFile.FileName); headers.Add((TarHeader)tarFile.FileHeader); using (Stream data = tarFile.Open()) using (StreamReader reader = new StreamReader(data)) { contents.Add(reader.ReadToEnd()); } } } } }
public void ReadTest() { using (Stream stream = File.OpenRead(@"Deb/libplist3_1.12-3.1_amd64.deb")) using (ArFile arFile = new ArFile(stream, leaveOpen: true)) { Collection <string> filenames = new Collection <string>(); Collection <ArHeader> headers = new Collection <ArHeader>(); while (arFile.Read()) { filenames.Add(arFile.FileName); headers.Add((ArHeader)arFile.FileHeader); arFile.Skip(); } Assert.Equal( new string[] { "debian-binary", "control.tar.gz", "data.tar.xz" }, filenames); } }
/// <summary> /// Extracts an archive file created with GNU ar /// </summary> /// <param name="fileEntry"> </param> /// <returns> </returns> /// public IEnumerable <FileEntry> Extract(FileEntry fileEntry, ExtractorOptions options, ResourceGovernor governor) { IEnumerable <FileEntry>?fileEntries = null; try { fileEntries = ArFile.GetFileEntries(fileEntry, options, governor); } catch (Exception e) { Logger.Debug(Extractor.DEBUG_STRING, ArchiveFileType.AR, fileEntry.FullPath, string.Empty, e.GetType()); if (e is OverflowException) { throw; } } if (fileEntries != null) { if (options.Parallel) { while (fileEntries.Any()) { var tempStore = new ConcurrentStack <FileEntry>(); var selectedEntries = fileEntries.Take(options.BatchSize); selectedEntries.AsParallel().ForAll(arEntry => { tempStore.PushRange(Context.ExtractFile(arEntry, options, governor).ToArray()); }); fileEntries = fileEntries.Skip(selectedEntries.Count()); while (tempStore.TryPop(out var result)) { if (result != null) { yield return(result); } } } } else { foreach (var entry in fileEntries) { foreach (var extractedFile in Context.ExtractFile(entry, options, governor)) { yield return(extractedFile); } } } } else { if (options.ExtractSelfOnFail) { yield return(fileEntry); } } }
/// <summary> /// Reads and parses the <c>debian-binary</c> file in the Debian archive. /// </summary> /// <param name="archive"> /// The archive to update with the data read from the <c>debian-binary</c> file. /// </param> /// <param name="package"> /// The package to update. /// </param> private static void ReadDebianBinary(ArFile archive, DebPackage package) { using (Stream stream = archive.Open()) using (StreamReader reader = new StreamReader(stream)) { var content = reader.ReadToEnd(); package.PackageFormatVersion = new Version(content); } }
/// <summary> /// Extracts an archive file created with GNU ar /// </summary> /// <param name="fileEntry"> </param> /// <returns> </returns> /// public async IAsyncEnumerable <FileEntry> ExtractAsync(FileEntry fileEntry, ExtractorOptions options, ResourceGovernor governor) { await foreach (var entry in ArFile.GetFileEntriesAsync(fileEntry, options, governor)) { await foreach (var extractedFile in Context.ExtractAsync(entry, options, governor)) { yield return(extractedFile); } } }
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); } } } }
/// <summary> /// Reads a <see cref="DebPackage"/> from a <see cref="Stream"/>. /// </summary> /// <param name="stream"> /// The <see cref="Stream"/> from which to read the package. /// </param> /// <returns> /// A <see cref="DebPackage"/> which represents the package. /// </returns> public static async Task <DebPackage> Read(Stream stream) { DebPackage package = new DebPackage(); using (ArFile archive = new ArFile(stream, leaveOpen: true)) { while (archive.Read()) { if (archive.FileName == "debian-binary") { await ReadDebianBinary(archive, package); } else if (archive.FileName == "control.tar.gz") { await ReadControlArchive(archive, package); } } } return(package); }
void Build() { int debberVer = 0; ini.GetValue("debber", "debber-version", ref debberVer); if (debberVer != 1) { throw new Exception("File requires a newer debber version. Please update!"); } string binVer = ini.ReadSetting("debber", "debian-binary"); if (binVer != "2.0") { throw new Exception("Invalid or unknown debian version!"); } packageVersion = SemanticVersion.Parse(ini.ReadSetting("package", "version")); packageName = ini.ReadSetting("package", "name"); packageFile = ini.ReadSetting("package", "output").Replace("{NAME}", packageName).Replace("{VERSION}", packageVersion.ToString()); FileSystem.TouchFile(packageFile); SystemConsole.WriteLine("Create <cyan>data.tar.gz<default>..."); byte[] data_tar_gz; using (MemoryStream ms = new MemoryStream()) { TarWriter tarFile = new TarWriter(ms, true); foreach (string line in ini.ReadSection("data.tgz", true)) { string[] parts = line.Split(':'); if (parts.Length < 2) { continue; } switch (parts[0].Trim()) { case "directory": PackDirectory(tarFile, parts[1]); break; case "file": PackFiles(tarFile, parts); break; default: throw new Exception(string.Format("Invalid setting {0} at [data.tgz]!", line)); } } tarFile.Close(); data_tar_gz = ms.ToArray(); } SystemConsole.WriteLine("Create <cyan>control.tar.gz<default>..."); byte[] control_tar_gz; using (MemoryStream tarStream = new MemoryStream()) { TarWriter tarFile = new TarWriter(tarStream, true); WriteControlFile(tarFile, "control", 640); #region md5sums using (MemoryStream ms = new MemoryStream()) { DataWriter writer = new DataWriter(ms); foreach (KeyValuePair <string, string> md5sum in md5sums) { writer.Write(md5sum.Value); writer.Write(" "); writer.Write(md5sum.Key); writer.Write("\n"); } writer.Close(); SystemConsole.WriteLine(" file: <cyan>md5sums"); tarFile.AddFile("md5sums", ms.ToArray()); } #endregion WriteControlFile(tarFile, "conffiles", 640); WriteControlFile(tarFile, "preinst", 700); WriteControlFile(tarFile, "postinst", 700); WriteControlFile(tarFile, "prerm", 700); WriteControlFile(tarFile, "postrm", 700); tarFile.Close(); control_tar_gz = tarStream.ToArray(); } using (MemoryStream ms = new MemoryStream()) { var arFile = ArFile.CreateNewAr(ms); arFile.WriteHeader(ArHeader.CreateFile("debian-binary", 4)); arFile.WriteData(Encoding.ASCII.GetBytes("2.0\n")); arFile.WriteHeader(ArHeader.CreateFile("control.tar.gz", control_tar_gz.Length)); arFile.WriteData(control_tar_gz); arFile.WriteHeader(ArHeader.CreateFile("data.tar.gz", data_tar_gz.Length)); arFile.WriteData(data_tar_gz); arFile.Close(); File.WriteAllBytes(packageFile, ms.ToArray()); SystemConsole.WriteLine("Completed <green>{0}<default> ...", packageFile); } }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="name">The name of the symbol.</param> /// <param name="file">The associated file entry this symbol is coming from <see cref="ArArchiveFile.Files"/>.</param> public ArSymbol(string name, ArFile file) : this() { Name = name; File = file; }
private static async Task ReadControlArchive(ArFile archive, DebPackage package) { package.ControlExtras = new Dictionary <string, DebPackageControlFileData>(); package.Md5Sums = new Dictionary <string, string>(); using (Stream stream = archive.Open()) using (GZipDecompressor decompressedStream = new GZipDecompressor(stream, leaveOpen: true)) using (TarFile tarFile = new TarFile(decompressedStream, leaveOpen: true)) { while (tarFile.Read()) { switch (tarFile.FileName) { case "./control": case "control": using (Stream controlFile = tarFile.Open()) { package.ControlFile = ControlFileParser.Read(controlFile); } break; case "./md5sums": using (var sums = new StreamReader(tarFile.Open())) { string line; while ((line = await sums.ReadLineAsync()) != null) { var s = line.Split(new[] { " " }, 2, StringSplitOptions.None); package.Md5Sums[s[1]] = s[0]; } } break; case "./preinst": package.PreInstallScript = tarFile.ReadAsUtf8String(); break; case "./postinst": package.PostInstallScript = tarFile.ReadAsUtf8String(); break; case "./prerm": package.PreRemoveScript = tarFile.ReadAsUtf8String(); break; case "./postrm": package.PostRemoveScript = tarFile.ReadAsUtf8String(); break; case "./": tarFile.Skip(); break; default: package.ControlExtras[tarFile.FileName] = new DebPackageControlFileData { Mode = tarFile.FileHeader.FileMode, Contents = tarFile.ReadAsUtf8String() }; break; } } } }