mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-21 00:05:26 +03:00
Backport pull request #15263 from jellyfin/release-10.11.z
Resolve symlinks for static media source infos
Original-merge: 3b2d64995a
Merged-by: crobibero <cody@robibe.ro>
Backported-by: Bond_009 <bond.009@outlook.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.IO;
|
||||
@@ -61,4 +62,77 @@ public static class FileSystemHelper
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target of the specified file link.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This helper exists because of this upstream runtime issue; https://github.com/dotnet/runtime/issues/92128.
|
||||
/// </remarks>
|
||||
/// <param name="linkPath">The path of the file link.</param>
|
||||
/// <param name="returnFinalTarget">true to follow links to the final target; false to return the immediate next link.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileInfo"/> if the <paramref name="linkPath"/> is a link, regardless of if the target exists; otherwise, <c>null</c>.
|
||||
/// </returns>
|
||||
public static FileInfo? ResolveLinkTarget(string linkPath, bool returnFinalTarget = false)
|
||||
{
|
||||
// Check if the file exists so the native resolve handler won't throw at us.
|
||||
if (!File.Exists(linkPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!returnFinalTarget)
|
||||
{
|
||||
return File.ResolveLinkTarget(linkPath, returnFinalTarget: false) as FileInfo;
|
||||
}
|
||||
|
||||
if (File.ResolveLinkTarget(linkPath, returnFinalTarget: false) is not FileInfo targetInfo)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var currentPath = targetInfo.FullName;
|
||||
var visited = new HashSet<string>(StringComparer.Ordinal) { linkPath, currentPath };
|
||||
while (File.ResolveLinkTarget(currentPath, returnFinalTarget: false) is FileInfo linkInfo)
|
||||
{
|
||||
var targetPath = linkInfo.FullName;
|
||||
|
||||
// If an infinite loop is detected, return the file info for the
|
||||
// first link in the loop we encountered.
|
||||
if (!visited.Add(targetPath))
|
||||
{
|
||||
return new FileInfo(targetPath);
|
||||
}
|
||||
|
||||
targetInfo = linkInfo;
|
||||
currentPath = targetPath;
|
||||
|
||||
// Exit if the target doesn't exist, so the native resolve handler won't throw at us.
|
||||
if (!targetInfo.Exists)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return targetInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target of the specified file link.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This helper exists because of this upstream runtime issue; https://github.com/dotnet/runtime/issues/92128.
|
||||
/// </remarks>
|
||||
/// <param name="fileInfo">The file info of the file link.</param>
|
||||
/// <param name="returnFinalTarget">true to follow links to the final target; false to return the immediate next link.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="FileInfo"/> if the <paramref name="fileInfo"/> is a link, regardless of if the target exists; otherwise, <c>null</c>.
|
||||
/// </returns>
|
||||
public static FileInfo? ResolveLinkTarget(FileInfo fileInfo, bool returnFinalTarget = false)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(fileInfo);
|
||||
|
||||
return ResolveLinkTarget(fileInfo.FullName, returnFinalTarget);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user