mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-02 05:48:47 +01:00
Only resolve symlinks on playback (#16965)
Only resolve symlinks on playback
This commit is contained in:
@@ -24,6 +24,7 @@ using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
@@ -176,6 +177,7 @@ namespace Emby.Server.Implementations.Library
|
||||
public async Task<IReadOnlyList<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken)
|
||||
{
|
||||
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
|
||||
ResolveSymlinkPaths(mediaSources, enablePathSubstitution);
|
||||
|
||||
// If file is strm or main media stream is missing, force a metadata refresh with remote probing
|
||||
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder
|
||||
@@ -192,6 +194,7 @@ namespace Emby.Server.Implementations.Library
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
|
||||
ResolveSymlinkPaths(mediaSources, enablePathSubstitution);
|
||||
}
|
||||
|
||||
var dynamicMediaSources = await GetDynamicMediaSources(item, cancellationToken).ConfigureAwait(false);
|
||||
@@ -324,6 +327,28 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves symlinked file paths on the supplied sources to the real on-disk target.
|
||||
/// Skipped when <paramref name="enablePathSubstitution"/> is set because the path may
|
||||
/// already have been rewritten to a UNC/URL meant for the client to consume directly.
|
||||
/// </summary>
|
||||
private static void ResolveSymlinkPaths(IReadOnlyList<MediaSourceInfo> sources, bool enablePathSubstitution)
|
||||
{
|
||||
if (enablePathSubstitution)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var source in sources)
|
||||
{
|
||||
if (source.Protocol == MediaProtocol.File
|
||||
&& FileSystemHelper.ResolveLinkTarget(source.Path, returnFinalTarget: true) is { Exists: true } target)
|
||||
{
|
||||
source.Path = target.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetKeyProperties(IMediaSourceProvider provider, MediaSourceInfo mediaSource)
|
||||
{
|
||||
var prefix = provider.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture) + LiveStreamIdDelimiter;
|
||||
|
||||
@@ -119,7 +119,18 @@ public class LibraryController : BaseJellyfinApiController
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return PhysicalFile(item.Path, MimeTypes.GetMimeType(item.Path), true);
|
||||
var filePath = item.Path;
|
||||
if (item.IsFileProtocol)
|
||||
{
|
||||
// PhysicalFile does not work well with symlinks at the moment.
|
||||
var resolved = FileSystemHelper.ResolveLinkTarget(filePath, returnFinalTarget: true);
|
||||
if (resolved is not null && resolved.Exists)
|
||||
{
|
||||
filePath = resolved.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
return PhysicalFile(filePath, MimeTypes.GetMimeType(filePath), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -23,7 +23,6 @@ using MediaBrowser.Controller.Chapters;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaSegments;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
@@ -1134,15 +1133,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
var protocol = item.PathProtocol;
|
||||
|
||||
// Resolve the item path so everywhere we use the media source it will always point to
|
||||
// the correct path even if symlinks are in use. Calling ResolveLinkTarget on a non-link
|
||||
// path will return null, so it's safe to check for all paths.
|
||||
var itemPath = item.Path;
|
||||
if (protocol is MediaProtocol.File && FileSystemHelper.ResolveLinkTarget(itemPath, returnFinalTarget: true) is { Exists: true } linkInfo)
|
||||
{
|
||||
itemPath = linkInfo.FullName;
|
||||
}
|
||||
|
||||
var info = new MediaSourceInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user