Skip to content
Prev Previous commit
Next Next commit
Address feedback
  • Loading branch information
jozkee authored and github-actions committed Sep 28, 2022
commit 512eb0405c9748ca1321f9617636d3f88dfdd231
1 change: 1 addition & 0 deletions src/libraries/Common/src/System/IO/PathInternal.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static partial class PathInternal
internal const string DirectorySeparatorCharAsString = "/";
internal const string ParentDirectoryPrefix = @"../";
internal const string DirectorySeparators = DirectorySeparatorCharAsString;
internal static ReadOnlySpan<byte> Utf8DirectorySeparators => "/"u8;

internal static int GetRootLength(ReadOnlySpan<char> path)
{
Expand Down
1 change: 1 addition & 0 deletions src/libraries/Common/src/System/IO/PathInternal.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ internal static partial class PathInternal
internal const string DevicePathPrefix = @"\\.\";
internal const string ParentDirectoryPrefix = @"..\";
internal const string DirectorySeparators = @"\/";
internal static ReadOnlySpan<byte> Utf8DirectorySeparators => @"\/"u8;

internal const int MaxShortPath = 260;
internal const int MaxShortDirectoryPath = 248;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ internal sealed partial class TarHeader

private static ReadOnlySpan<byte> GnuMagicBytes => "ustar "u8;
private static ReadOnlySpan<byte> GnuVersionBytes => " \0"u8;
private static ReadOnlySpan<byte> SeparatorsAsBytes => Encoding.UTF8.GetBytes(PathInternal.DirectorySeparators);

// Predefined text for the Name field of a GNU long metadata entry. Applies for both LongPath ('L') and LongLink ('K').
private const string GnuLongMetadataName = "././@LongLink";
Expand Down Expand Up @@ -398,9 +397,9 @@ private int WriteUstarName(Span<byte> buffer)
return WriteLeftAlignedBytesAndGetChecksum(nameAndPrefixBytes, buffer.Slice(FieldLocations.Name, FieldLengths.Name));
}

int lastIdx = nameAndPrefixBytes.LastIndexOfAny(SeparatorsAsBytes);
ReadOnlySpan<byte> name = stackalloc byte[0];
ReadOnlySpan<byte> prefix = stackalloc byte[0];
int lastIdx = nameAndPrefixBytes.LastIndexOfAny(PathInternal.Utf8DirectorySeparators);
scoped ReadOnlySpan<byte> name;
scoped ReadOnlySpan<byte> prefix;

if (lastIdx == -1)
{
Expand All @@ -410,32 +409,21 @@ private int WriteUstarName(Span<byte> buffer)
else
{
name = nameAndPrefixBytes.Slice(lastIdx + 1);

if (lastIdx > 0)
{
prefix = nameAndPrefixBytes.Slice(0, lastIdx);
}
else
{
// We cannot neglect the separator if that's the only thing we can place in prefix.
prefix = nameAndPrefixBytes.Slice(0, 1);
}
prefix = nameAndPrefixBytes.Slice(0, Math.Max(lastIdx, 1)); // need at least the separator
}

// At this point nameAndPrefixBytes.Length > 100.
// Attempt to split it in a way it can use prefix.
while (prefix.Length - name.Length > FieldLengths.Prefix)
{
lastIdx = prefix.LastIndexOfAny(SeparatorsAsBytes);
if (lastIdx == -1) { break; }

name = nameAndPrefixBytes.Slice(lastIdx + 1);
if (lastIdx > 0)
{
prefix = prefix.Slice(0, lastIdx);
}
else
lastIdx = prefix.LastIndexOfAny(PathInternal.Utf8DirectorySeparators);
if (lastIdx < 0)
{
prefix = prefix.Slice(0, 1);
break;
}

name = nameAndPrefixBytes.Slice(lastIdx + 1);
prefix = nameAndPrefixBytes.Slice(0, Math.Max(lastIdx, 1)); // need at least the separator
}

if (prefix.Length <= FieldLengths.Prefix && name.Length <= FieldLengths.Name)
Expand Down