Merge pull request #16456 from joshuaboniface/fix-path-filesystem-logic

This commit is contained in:
Joshua M. Boniface 2026-04-09 00:37:00 -04:00 committed by GitHub
commit e3b5cf4996
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 10 deletions

View file

@ -28,22 +28,44 @@ public static class StorageHelper
}
/// <summary>
/// Gets the free space of a specific directory.
/// Gets the free space of the parent filesystem of a specific directory.
/// </summary>
/// <param name="path">Path to a folder.</param>
/// <returns>The number of bytes available space.</returns>
/// <returns>Various details about the parent filesystem containing the directory.</returns>
public static FolderStorageInfo GetFreeSpaceOf(string path)
{
try
{
var driveInfo = new DriveInfo(path);
// Fully resolve the given path to an actual filesystem target, in case it's a symlink or similar.
var resolvedPath = ResolvePath(path);
// We iterate all filesystems reported by GetDrives() here, and attempt to find the best
// match that contains, as deep as possible, the given path.
// This is required because simply calling `DriveInfo` on a path returns that path as
// the Name and RootDevice, which is not at all how this should work.
var allDrives = DriveInfo.GetDrives();
DriveInfo? bestMatch = null;
foreach (DriveInfo d in allDrives)
{
if (resolvedPath.StartsWith(d.RootDirectory.FullName, StringComparison.InvariantCultureIgnoreCase) &&
(bestMatch is null || d.RootDirectory.FullName.Length > bestMatch.RootDirectory.FullName.Length))
{
bestMatch = d;
}
}
if (bestMatch is null)
{
throw new InvalidOperationException($"The path `{path}` has no matching parent device. Space check invalid.");
}
return new FolderStorageInfo()
{
Path = path,
FreeSpace = driveInfo.AvailableFreeSpace,
UsedSpace = driveInfo.TotalSize - driveInfo.AvailableFreeSpace,
StorageType = driveInfo.DriveType.ToString(),
DeviceId = driveInfo.Name,
ResolvedPath = resolvedPath,
FreeSpace = bestMatch.AvailableFreeSpace,
UsedSpace = bestMatch.TotalSize - bestMatch.AvailableFreeSpace,
StorageType = bestMatch.DriveType.ToString(),
DeviceId = bestMatch.Name,
};
}
catch
@ -51,6 +73,7 @@ public static class StorageHelper
return new FolderStorageInfo()
{
Path = path,
ResolvedPath = path,
FreeSpace = -1,
UsedSpace = -1,
StorageType = null,
@ -59,6 +82,26 @@ public static class StorageHelper
}
}
/// <summary>
/// Walk a path and fully resolve any symlinks within it.
/// </summary>
private static string ResolvePath(string path)
{
var parts = path.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);
var current = Path.DirectorySeparatorChar.ToString();
foreach (var part in parts)
{
current = Path.Combine(current, part);
var resolved = new DirectoryInfo(current).ResolveLinkTarget(returnFinalTarget: true);
if (resolved is not null)
{
current = resolved.FullName;
}
}
return current;
}
/// <summary>
/// Gets the underlying drive data from a given path and checks if the available storage capacity matches the threshold.
/// </summary>