Ejemplo n.º 1
0
    /// <summary>
    /// Adds a downloaded file to the implementation.
    /// </summary>
    /// <param name="builder">The builder.</param>
    /// <param name="retrievalMethod">The metadata of the file.</param>
    /// <param name="stream">The contents of the file.</param>
    /// <param name="handler">A callback object used when the the user needs to be informed about IO tasks.</param>
    /// <param name="tag">A <see cref="ITask.Tag"/> used to group progress bars. Usually <see cref="ManifestDigest.Best"/>.</param>
    /// <exception cref="UnauthorizedAccessException">Access to a resource was denied.</exception>
    /// <exception cref="IOException">An IO operation failed.</exception>
    public static void Add(this IBuilder builder, DownloadRetrievalMethod retrievalMethod, Stream stream, ITaskHandler handler, object?tag = null)
    {
        switch (retrievalMethod)
        {
        case SingleFile singleFile:
            builder.AddFile(singleFile, stream);
            break;

        case Archive archive:
            builder.AddArchive(archive, stream, handler, tag);
            break;

        default:
            throw new NotSupportedException($"Unknown download retrieval method: ${retrievalMethod}");
        }
    }
Ejemplo n.º 2
0
    public Stream?OpenFileWriteStream(string path, long fileSize, DateTime lastWriteTime)
    {
        _cancellationToken.ThrowIfCancellationRequested();

        string relativePath = _normalizePath(path);

        if (relativePath == null)
        {
            return(null);
        }

        _pipe = new();

        var readStream = _pipe.Reader.AsStream().WithLength(fileSize);

        _task = Task.Run(() => _builder.AddFile(relativePath, readStream, DateTime.SpecifyKind(lastWriteTime, DateTimeKind.Utc)), _cancellationToken);

        return(_pipe.Writer.AsStream());
    }
Ejemplo n.º 3
0
    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));
            }
        }
    }
Ejemplo n.º 4
0
    /// <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
        });
Ejemplo n.º 5
0
    /// <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
    }
Ejemplo n.º 6
0
    /// <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"
        })
Ejemplo n.º 7
0
 /// <inheritdoc/>
 public void AddFile(string path, Stream stream, UnixTime modifiedTime, bool executable = false)
 => _underlyingBuilder.AddFile(Path.Combine(_prefix, path), stream, modifiedTime, executable);
Ejemplo n.º 8
0
 /// <summary>
 /// Adds a file to the implementation.
 /// </summary>
 /// <param name="builder">The builder.</param>
 /// <param name="metadata">The metadata of the file.</param>
 /// <param name="stream">The contents of the file.</param>
 /// <exception cref="UnauthorizedAccessException">Access to a resource was denied.</exception>
 /// <exception cref="IOException">An IO operation failed.</exception>
 public static void AddFile(this IBuilder builder, SingleFile metadata, Stream stream)
 => builder.AddFile(metadata.Destination, stream, 0, metadata.Executable);