Ejemplo n.º 1
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.º 2
0
 /// <inheritdoc/>
 public void AddHardlink(string path, string target, bool executable = false)
 => _underlyingBuilder.AddHardlink(Path.Combine(_prefix, path), Path.Combine(_prefix, target), executable);