/// <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));
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }