private static void ApplyCentral(ZipFile zipFile, string?subDir, IBuilder builder) { for (int i = 0; i < zipFile.Count; i++) { var entry = zipFile[i]; string?relativePath = NormalizePath(entry.Name, subDir); if (string.IsNullOrEmpty(relativePath)) { continue; } if (entry.IsDirectory) { builder.AddDirectory(relativePath); } else if (entry.IsFile) { if (IsSymlink(entry)) { builder.TurnIntoSymlink(relativePath); } else if (IsExecutable(entry)) { builder.MarkAsExecutable(relativePath); } } } }
/// <summary> /// Adds a subdirectory to the implementation and returns a wrapped <see cref="IBuilder"/> to elements inside this subdirectory. /// </summary> /// <param name="builder">The builder.</param> /// <param name="path">The path of the directory to create relative to the implementation root.</param> /// <exception cref="UnauthorizedAccessException">Access to a resource was denied.</exception> /// <exception cref="IOException">An IO operation failed.</exception> /// <returns>An <see cref="IBuilder"/> wrapped around <paramref name="builder"/> that prepends <paramref name="path"/> to paths.</returns> public static IBuilder BuildDirectory(this IBuilder builder, string?path) { if (string.IsNullOrEmpty(path)) { return(builder); } builder.AddDirectory(path); return(new PrefixBuilder(builder, path)); }
private void ExtractFiles(ZipInputStream zipStream, string?subDir, IBuilder builder) { while (zipStream.GetNextEntry() is {} entry) { Handler.CancellationToken.ThrowIfCancellationRequested(); string?relativePath = NormalizePath(entry.Name, subDir); if (string.IsNullOrEmpty(relativePath)) { continue; } if (entry.IsDirectory) { builder.AddDirectory(relativePath); } else if (entry.IsFile) { builder.AddFile(relativePath, zipStream.WithLength(entry.Size), GetTimestamp(entry)); } } }
/// <inheritdoc/> public override void Extract(IBuilder builder, Stream stream, string?subDir = null) { EnsureSeekable(stream, seekableStream => { try { var reader = SevenZipArchive.Open(seekableStream).ExtractAllEntries(); while (reader.MoveToNextEntry()) { Handler.CancellationToken.ThrowIfCancellationRequested(); var entry = reader.Entry; string?relativePath = NormalizePath(entry.Key, subDir); if (relativePath == null) { continue; } if (entry.IsDirectory) { builder.AddDirectory(relativePath); } else { using var elementStream = reader.OpenEntryStream().WithLength(entry.Size); builder.AddFile(relativePath, elementStream, entry.LastModifiedTime ?? new UnixTime()); } } } #region Error handling catch (Exception ex) when(ex is InvalidOperationException or ExtractionException or IndexOutOfRangeException) { // Wrap exception since only certain exception types are allowed throw new IOException(Resources.ArchiveInvalid, ex); } #endregion });
/// <inheritdoc/> public override void Extract(IBuilder builder, Stream stream, string?subDir = null) { try { using var reader = RarReader.Open(stream, new() { LeaveStreamOpen = true }); while (reader.MoveToNextEntry()) { Handler.CancellationToken.ThrowIfCancellationRequested(); var entry = reader.Entry; string?relativePath = NormalizePath(entry.Key, subDir); if (relativePath == null) { continue; } if (entry.IsDirectory) { builder.AddDirectory(relativePath); } else { using var elementStream = reader.OpenEntryStream(); builder.AddFile(relativePath, elementStream, entry.LastModifiedTime ?? default); } } } #region Error handling catch (ExtractionException ex) { // Wrap exception since only certain exception types are allowed throw new IOException(Resources.ArchiveInvalid + "\n" + ex.Message, ex); } #endregion }
/// <inheritdoc/> public override void Extract(IBuilder builder, Stream stream, string?subDir = null) { var symlinks = new List <(string path, string target)>(); var hardlinks = new List <(string path, string existingPath, bool executable)>(); try { using var tarStream = new TarInputStream(stream, Encoding.UTF8) { IsStreamOwner = false }; while (tarStream.GetNextEntry() is {} entry) { Handler.CancellationToken.ThrowIfCancellationRequested(); string?relativePath = NormalizePath(entry.Name, subDir); if (string.IsNullOrEmpty(relativePath)) { continue; } switch (entry.TarHeader.TypeFlag) { case TarHeader.LF_SYMLINK: symlinks.Add((relativePath, entry.TarHeader.LinkName)); break; case TarHeader.LF_LINK: string?targetPath = NormalizePath(entry.TarHeader.LinkName, subDir); if (string.IsNullOrEmpty(targetPath)) { throw new IOException($"The hardlink '{relativePath}' in the archive points to a non-existent file '{entry.TarHeader.LinkName}'."); } hardlinks.Add((relativePath, targetPath, IsExecutable(entry))); break; case TarHeader.LF_DIR: builder.AddDirectory(relativePath); break; case TarHeader.LF_NORMAL or TarHeader.LF_OLDNORM: builder.AddFile(relativePath, tarStream.WithLength(entry.Size), entry.TarHeader.ModTime, IsExecutable(entry)); break; default: throw new NotSupportedException($"Archive entry '{entry.Name}' has unsupported type: {entry.TarHeader.TypeFlag}"); } } foreach ((string path, string target) in symlinks) { builder.AddSymlink(path, target); } foreach ((string path, string existingPath, bool executable) in hardlinks) builder.AddHardlink(path, existingPath, executable); } #region Error handling catch (Exception ex) when(ex is SharpZipBaseException or InvalidDataException or ArgumentOutOfRangeException or IndexOutOfRangeException or { Message: "Data Error" })
/// <inheritdoc/> public void AddDirectory(string path) => _underlyingBuilder.AddDirectory(Path.Combine(_prefix, path));