diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxGlobalExtendedAttributesTarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxGlobalExtendedAttributesTarEntry.cs index 832996693624f1e7a01cea99dd888163d5b8b9cc..94ba60167f721277a04f97bc278127e57d0f74f4 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxGlobalExtendedAttributesTarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxGlobalExtendedAttributesTarEntry.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; namespace System.Formats.Tar { @@ -26,7 +25,7 @@ internal PaxGlobalExtendedAttributesTarEntry(TarHeader header, TarReader readerO /// An enumeration of string key-value pairs that represents the metadata to include as Global Extended Attributes. /// is . public PaxGlobalExtendedAttributesTarEntry(IEnumerable> globalExtendedAttributes) - : base(TarEntryType.GlobalExtendedAttributes, TarHeader.GlobalHeadFormatPrefix, TarEntryFormat.Pax, isGea: true) + : base(TarEntryType.GlobalExtendedAttributes, nameof(PaxGlobalExtendedAttributesTarEntry), TarEntryFormat.Pax, isGea: true) // Name == name of type for lack of a better temporary name until the entry is written { ArgumentNullException.ThrowIfNull(globalExtendedAttributes); _header.InitializeExtendedAttributesWithExisting(globalExtendedAttributes); diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 884c2bf1bcaf907ca8819f925fcde800b8298fbd..40b0e330b314b4dd802dc2b562432f85a3a64c83 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -893,32 +893,22 @@ private string GenerateExtendedAttributeName() } // Gets the special name for the 'name' field in a global extended attribute entry. - // Format: "%d/GlobalHead.%p/%n" + // Format: "%d/GlobalHead.%p.%n" // - %d: The path of the $TMPDIR variable, if found. Otherwise, the value is '/tmp'. // - %p: The current process ID. - // - %n: The sequence number of the global extended header record of the archive, starting at 1. In our case, since we only generate one, the value is always 1. + // - %n: The sequence number of the global extended header record of the archive, starting at 1. // If the path of $TMPDIR makes the final string too long to fit in the 'name' field, // then the TMPDIR='/tmp' is used. private static string GenerateGlobalExtendedAttributeName(int globalExtendedAttributesEntryNumber) { Debug.Assert(globalExtendedAttributesEntryNumber >= 1); - string tmpDir = Path.GetTempPath(); - if (Path.EndsInDirectorySeparator(tmpDir)) - { - tmpDir = Path.TrimEndingDirectorySeparator(tmpDir); - } - int processId = Environment.ProcessId; - - string result = string.Format(GlobalHeadFormatPrefix, tmpDir, processId); - string suffix = $".{globalExtendedAttributesEntryNumber}"; // GEA sequence number - if (result.Length + suffix.Length >= FieldLengths.Name) - { - result = string.Format(GlobalHeadFormatPrefix, "/tmp", processId); - } - result += suffix; + ReadOnlySpan tmp = Path.TrimEndingDirectorySeparator(Path.GetTempPath()); - return result; + string result = $"{tmp}/GlobalHead.{Environment.ProcessId}.{globalExtendedAttributesEntryNumber}"; + return result.Length >= FieldLengths.Name ? + string.Concat("/tmp", result.AsSpan(tmp.Length)) : + result; } private static int GetUtf8TextLength(ReadOnlySpan text) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.cs index 65fdda022b32b6cc31ec1eabf6a1146b54856d13..9510746a5cab159fb3f53d39aba445cf3cbfcd54 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.cs @@ -39,11 +39,6 @@ internal sealed partial class TarHeader private const string PaxEaDevMajor = "devmajor"; private const string PaxEaDevMinor = "devminor"; - // Global Extended Attribute entries have a special format in the Name field: - // "{tmpFolder}/GlobalHead.{processId}.{GEAEntryNumber}" - // Excludes ".{GEAEntryNumber}" because the number gets added on write. - internal const string GlobalHeadFormatPrefix = "{0}/GlobalHead.{1}"; - internal Stream? _dataStream; // Position in the stream where the data ends in this header. diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs index b0c9d636420b5250d16605219278a6073f8dd7e6..fc6445a3b3e97140da40ddc6340ab5958910eb03 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Entry.Pax.Tests.cs @@ -378,7 +378,9 @@ public async Task Add_Empty_GlobalExtendedAttributes_Async() await using (TarWriter writer = new TarWriter(archive, leaveOpen: true)) { PaxGlobalExtendedAttributesTarEntry gea = new PaxGlobalExtendedAttributesTarEntry(new Dictionary()); + Assert.Equal("PaxGlobalExtendedAttributesTarEntry", gea.Name); await writer.WriteEntryAsync(gea); + Assert.Matches(@".*/GlobalHead\.\d+\.\d+", gea.Name); } archive.Seek(0, SeekOrigin.Begin);