in Core/src/Impl/PathUtil.cs [37:126]
public static ValidateAndFixErrors ValidateAndFixDataPath(this SymbolStoragePath storagePath, StorageFormat storageFormat, out SymbolStoragePath fixedStoragePath)
{
fixedStoragePath = storagePath;
var parts = storagePath.GetPathComponents();
if (parts.Length != 2 && parts.Length != 3)
return ValidateAndFixErrors.Error;
if (parts.Any(x => x.Length == 0))
return ValidateAndFixErrors.Error;
switch (storageFormat)
{
case StorageFormat.Normal:
{
var namePartLower = parts[0].ToLowerInvariant();
var hashPartLower = parts[1].ToLowerInvariant();
var nameExt = Path.GetExtension(namePartLower.AsSpan());
if (nameExt is PdbExt)
{
if (!hashPartLower.All(IsHex))
return ValidateAndFixErrors.Error;
if (hashPartLower.Length == 40)
{
// Note: See https://github.com/dotnet/symstore/blob/master/docs/specs/SSQP_Key_Conventions.md#portable-pdb-signature
// This code expects that the real age never be 0xFFFFFFFF!!!
if (hashPartLower.Substring(32, 8) == "ffffffff")
hashPartLower = hashPartLower.Substring(0, 32) + "FFFFFFFF";
}
}
else if (nameExt is DllExt || nameExt is ExeExt)
{
if (!hashPartLower.All(IsHex))
return ValidateAndFixErrors.Error;
if (hashPartLower.Length > 8)
{
// Note: See https://github.com/dotnet/symstore/blob/master/docs/specs/SSQP_Key_Conventions.md#pe-timestamp-filesize
hashPartLower = hashPartLower.Substring(0, 8).ToUpperInvariant() + hashPartLower.Substring(8);
}
}
var builder = new StringBuilder()
.Append(namePartLower)
.Append(SymbolStoragePath.DirectorySeparator)
.Append(hashPartLower);
if (parts.Length > 2)
{
var filePartLower = parts[2].ToLowerInvariant();
if (filePartLower.EndsWith('_'))
{
if (namePartLower.Substring(0, namePartLower.Length - 1) != filePartLower.Substring(0, namePartLower.Length - 1))
return ValidateAndFixErrors.Error;
}
else if (namePartLower != filePartLower)
return ValidateAndFixErrors.Error;
builder
.Append(SymbolStoragePath.DirectorySeparator)
.Append(filePartLower);
}
var newPath = builder.ToString();
if (storagePath == newPath)
return ValidateAndFixErrors.Ok;
fixedStoragePath = new SymbolStoragePath(newPath);
return ValidateAndFixErrors.CanBeFixed;
}
case StorageFormat.LowerCase:
{
var pathOrig = storagePath.ToLower();
if (storagePath == pathOrig)
return ValidateAndFixErrors.Ok;
fixedStoragePath = pathOrig;
return ValidateAndFixErrors.CanBeFixed;
}
case StorageFormat.UpperCase:
{
var pathOrig = storagePath.ToUpper();
if (storagePath == pathOrig)
return ValidateAndFixErrors.Ok;
fixedStoragePath = pathOrig;
return ValidateAndFixErrors.CanBeFixed;
}
default:
throw new ArgumentOutOfRangeException(nameof(storageFormat), storageFormat, null);
}
}