Skip to content

Erroneous IOException in TarWriter.WriteEntry on MacOS #81047

@jacobcarpenter

Description

@jacobcarpenter

Description

dotnet/sdk-container-builds#246

The new dotnet publish container support crashes on MacOS. This appears due to an error in TarWriter.WriteEntry.

Specifically, the stack trace points to this line, but the behavior any deeper than that is pretty opaque to me.

I've written a simple dotnet new console app that repros the behavior; here is the stack trace output from running it:

Unhandled exception. System.IO.IOException: No such file or directory
   at Interop.Sys.GetGroupName(UInt32 gid)
   at System.Formats.Tar.TarWriter.ConstructEntryForWriting(String fullPath, String entryName, FileOptions fileOptions)
   at System.Formats.Tar.TarWriter.WriteEntry(String fileName, String entryName)
   at Program.<Main>$(String[] args) in /Users/jcarpenter/projects/personal/tar-bug/Program.cs:line 18

Reproduction Steps

On a Mac, in a new empty directory:

  1. dotnet new
  2. Create a file named example-file.txt:
echo 'Plain text file to be included in a tar.' > example-file.txt
  1. Replace Program.cs with:
using System.Formats.Tar;
using System.IO.Compression;

File.Delete("example-output.tar");
using var writeStream = File.Create("example-output.tar");

// Initialization roughly corresponds to crashing scenario in Microsoft.NET.Build.Containers/Layers.cs:
// https://github.com/dotnet/sdk-container-builds/blob/86ad14026fc68bb8967e662f49ffb3c105050bca/Microsoft.NET.Build.Containers/Layer.cs#L47
using var compressionStream = new GZipStream(writeStream, CompressionMode.Compress, leaveOpen: true);
using var tarWriter = new TarWriter(compressionStream, TarEntryFormat.Gnu, leaveOpen: true);

// On MacOS, we're able to write to the tar by explicitly creating a GnuTarEntry instance
var workingEntry = new GnuTarEntry(TarEntryType.RegularFile, "working/example-file.txt");
workingEntry.DataStream = File.OpenRead("example-file.txt");
tarWriter.WriteEntry(workingEntry); // works!

// On MacOS, this crashes with an erroneous System.IO.IOException: No such file or directory
tarWriter.WriteEntry("example-file.txt", "broken/example-file.txt"); // crashes
  1. dotnet run

Expected behavior

A tar should be created with entries for working/example-file.txt and broken/example-file.text.

Actual behavior

Instead, the program crashes when calling the WriteEntry overload that takes two strings (line 18 in the minimal repro).

If you comment out the offending line, the program produces a tar successfully.

Regression?

No response

Known Workarounds

One workaround (that I haven't confirmed myself, but assume must work) is to run this on Windows instead.

Another workaround is to avoid the crashing overload of WriteEntry and instead always explicitly create TarEntry instances. However, there is a lot of convenience baked into the crashing overload; so this workaround represents a higher implementation burden for creating the various types of TarEntries appropriately.

Configuration

» dotnet --info
.NET SDK:
 Version:   7.0.101
 Commit:    bb24aafa11

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  13.1
 OS Platform: Darwin
 RID:         osx.13-x64
 Base Path:   /usr/local/share/dotnet/sdk/7.0.101/

Host:
  Version:      7.0.1
  Architecture: x64
  Commit:       97203d38ba

[installed, etc. truncated]

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions