1

I'm trying to create a tar archive, then extract all the contents to a file using SharpZipLib. I am able to create the tar archive, but the program hangs when trying to extract it. I'm wondering if anyone else can reproduce this problem and see why it is happening. I've also tried using an example that allows for full control, and while debugging, it seems that my program hangs when tarIn.GetNextEntry() is called.

Here is my code

public void CreateTarAndExtract()
        {
            // create tar file
            string tarFile = "path_to_desktop\\tartest.tar";
            string inputFolder = "path_to_desktop\\testfolder";
            using (var output = File.OpenWrite(tarFile))
            {
                using (var archive = TarArchive.CreateOutputTarArchive(output, Encoding.UTF8))
                {
                    var trimLength = inputFolder.Length + 1;

                    foreach (var fsEntry in Directory.GetFileSystemEntries(inputFolder, "*", SearchOption.AllDirectories))
                    {
                        var entry = TarEntry.CreateEntryFromFile(fsEntry);
                        entry.Name = fsEntry.Substring(trimLength);
                        archive.WriteEntry(entry, false);
                    }
                }
            }

            // extract file
            string outputPath = "path_to_desktop\\tartest";
            using (var input = File.OpenRead(tarFile))
            {
                using (var archive = TarArchive.CreateInputTarArchive(input, Encoding.UTF8))
                {
                    archive.ExtractContents(outputPath);
                }
            }
        }
Raiden Hi
  • 61
  • 5
  • I reproduced your code and I have exactly the same result, the application freezes, I'm trying to fix the problem – BouRHooD Oct 01 '22 at 16:17
  • FYI: .NET 7 provides tar-related functions in the [System.Formats.Tar](https://learn.microsoft.com/en-us/dotnet/api/system.formats.tar?view=net-7.0) namespace. Although there is no final release of .NET 7 yet, a release candidate is available if you are interested in trying the System.Formats.Tar stuff out... –  Oct 01 '22 at 17:02
  • 1
    Async bug, don't call this on the main thread of a GUI app. – Hans Passant Oct 01 '22 at 18:23
  • @HansPassant yes it looks like that was the issue. I ran it in a different thread and it worked perfectly! Feel free to make an answer and I will mark it as solved. – Raiden Hi Oct 02 '22 at 03:34

1 Answers1

1

I get to unpack the tar archive this way:

    // extract file
    string outputPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "tartest");
    using (var input = File.OpenRead(tarFile))
    {
        ExtractTar(input, outputPath);
    }

    /// <summary>
    /// Extractes a <c>tar</c> archive to the specified directory.
    /// </summary>
    /// <param name="stream">The <i>.tar</i> to extract.</param>
    /// <param name="outputDir">Output directory to write the files.</param>
    public static void ExtractTar(Stream stream, string outputDir)
    {
        var buffer = new byte[100];
        while (true)
        {
            stream.Read(buffer, 0, 100);
            var name = Encoding.ASCII.GetString(buffer).Trim('\0');
            if (String.IsNullOrWhiteSpace(name))
                break;
            stream.Seek(24, SeekOrigin.Current);
            stream.Read(buffer, 0, 12);
            var size = Convert.ToInt64(Encoding.UTF8.GetString(buffer, 0, 12).Trim('\0').Trim(), 8);

            stream.Seek(376L, SeekOrigin.Current);

            var output = Path.Combine(outputDir, name);
            if (!Directory.Exists(Path.GetDirectoryName(output)))
                Directory.CreateDirectory(Path.GetDirectoryName(output));
            if (!name.Equals("./", StringComparison.InvariantCulture))
            {
                using (var str = File.Open(output, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    var buf = new byte[size];
                    stream.Read(buf, 0, buf.Length);
                    str.Write(buf, 0, buf.Length);
                }
            }

            var pos = stream.Position;

            var offset = 512 - (pos % 512);
            if (offset == 512)
                offset = 0;

            stream.Seek(offset, SeekOrigin.Current);
        }
    }
BouRHooD
  • 200
  • 1
  • 14
  • Thank you, this also solved my problem! However, I believe that HansPassant's comment that clarified it was an async bug solved the problem in a simpler way, so I will be accepting his answer once he posts it. – Raiden Hi Oct 02 '22 at 03:36