/// <inheritdoc/> public override async Task <IList <CompressedEntryModel> > ExtractAsync(string sourcePath, string destinationPath, CancellationToken ct) { if (string.IsNullOrWhiteSpace(sourcePath)) { throw new ArgumentNullException(nameof(sourcePath)); } if (string.IsNullOrWhiteSpace(destinationPath)) { throw new ArgumentNullException(nameof(destinationPath)); } if (ct == null) { throw new ArgumentNullException(nameof(ct)); } return(await Task.Run( () => { IList <CompressedEntryModel> entries = new List <CompressedEntryModel>(); // TODO: add options as parameters var options = new ReaderOptions() { LeaveStreamOpen = false, LookForHeader = false }; using (var file = File.OpenRead(sourcePath)) { using (var archive = ArchiveFactory.Open(file, options)) using (var comparer = new GenericNaturalComparer <IArchiveEntry>(e => e.Key)) { var sortedEntries = archive.Entries.Sort(comparer).Take(MaxCompressibleEntries); foreach (var entry in sortedEntries) { ct.ThrowIfCancellationRequested(); if (!entry.IsDirectory) { // TODO: add options as parameters var extractionOptions = new ExtractionOptions() { ExtractFullPath = false, Overwrite = false }; entry.WriteToDirectory(destinationPath, extractionOptions); entries.Add(EntryMapper.Map(entry)); } } } } return entries; }, ct)); }
/// <inheritdoc/> protected override async Task <IList <ArchivedEntryModel> > AbstractReadAsync(string path, CancellationToken ct) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException(nameof(path)); } if (ct == null) { throw new ArgumentNullException(nameof(ct)); } var fs = FileSystemStrategy.Create(path); if (fs == null) { throw new UnexpectedNullException("Filesystem could not be created based on the provided path."); } IList <ArchivedEntryModel> entries = new List <ArchivedEntryModel>(); var options = new ReaderOptions() { LeaveStreamOpen = false, LookForHeader = false }; using (var file = fs.File.OpenRead(path)) { using (var archive = ArchiveFactory.Open(file, options)) using (var comparer = new GenericNaturalComparer <IArchiveEntry>(e => e.Key)) { var sortedEntries = archive.Entries.Sort(comparer).Take(MaxArchivedEntries); foreach (var entry in sortedEntries) { ct.ThrowIfCancellationRequested(); entries.Add(EntryMapper.Map(entry)); } } } await Task.CompletedTask; return(entries); }
/// <inheritdoc/> protected override async Task <IList <CompressedEntryModel> > AbstractReadAsync(string path, CancellationToken ct) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException(nameof(path)); } if (ct == null) { throw new ArgumentNullException(nameof(ct)); } return(await Task.Run( () => { IList <CompressedEntryModel> entries = new List <CompressedEntryModel>(); // TODO: add options as parameters var options = new ReaderOptions() { LeaveStreamOpen = false, LookForHeader = false }; using (var file = File.OpenRead(path)) { using (var archive = ArchiveFactory.Open(file, options)) using (var comparer = new GenericNaturalComparer <IArchiveEntry>(e => e.Key)) { var sortedEntries = archive.Entries.Sort(comparer).Take(MaxCompressibleEntries); foreach (var entry in sortedEntries) { entries.Add(EntryMapper.Map(entry)); } } } return entries; }, ct)); }
/// <inheritdoc/> public override async Task <IList <ArchivedEntryModel> > ExtractAsync(string sourcePath, string destinationPath, CancellationToken ct, int level = 0) { Ensure.ArgumentNotNullOrWhiteSpace(sourcePath, nameof(sourcePath)); Ensure.ArgumentNotNullOrWhiteSpace(destinationPath, nameof(destinationPath)); Ensure.ArgumentNotNull(ct, nameof(ct)); if (level > 1) { throw new NotSupportedException("The archive contains too many levels."); } ct.ThrowIfCancellationRequested(); var fs = fileSystemStrategy.Create(sourcePath); if (fs == null) { throw new UnexpectedNullException("Filesystem could not be created based on the provided source path."); } IList <ArchivedEntryModel> entries = new List <ArchivedEntryModel>(); var options = new ReaderOptions() { LeaveStreamOpen = false, LookForHeader = false }; using (var file = fs.File.OpenRead(sourcePath)) { using (var archive = ArchiveFactory.Open(file, options)) using (var comparer = new GenericNaturalComparer <IArchiveEntry>(e => e.Key)) { var sortedEntries = archive.Entries .Where(e => !e.IsDirectory) .Sort(comparer) .Take(MaxArchivedEntries > 0 ? MaxArchivedEntries : int.MaxValue); if (MaxSizeKilobytes > 0 && sortedEntries.Sum(e => e.Size) > MaxSizeKilobytes * 1000) { throw new ArgumentException($"The file size exceeds the limit of {MaxSizeKilobytes} kilobytes."); } foreach (var entry in sortedEntries) { ct.ThrowIfCancellationRequested(); // extract all files to destination path (no sub-directories supported) var filename = fs.Path.GetFileName(entry.Key); if (string.IsNullOrWhiteSpace(filename)) { continue; } using (var ms = new MemoryStream()) { entry.WriteTo(ms); fs.File.WriteAllBytes(fs.Path.Combine(destinationPath, filename), ms.ToArray()); } var mappedEntry = EntryMapper.Map(entry); mappedEntry.Key = filename; entries.Add(mappedEntry); } } } if (entries.Count == 1 && entries[0].Key.EndsWith(".tar")) { return(await ExtractAsync(fs.Path.Combine(destinationPath, entries[0].Key), destinationPath, ct, ++level)); } // Delete tarball after extraction if (level == 1 && sourcePath.EndsWith(".tar")) { fs.File.Delete(sourcePath); } await Task.CompletedTask; return(entries); }