Fixed: Replaced mono symlink resolve logic to better handle errors.
This commit is contained in:
parent
bd6a38173e
commit
1c92ea58da
|
@ -382,6 +382,8 @@ namespace NzbDrone.Common.Disk
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IMount GetMount(string path)
|
public virtual IMount GetMount(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var mounts = GetMounts();
|
var mounts = GetMounts();
|
||||||
|
|
||||||
|
@ -390,6 +392,12 @@ namespace NzbDrone.Common.Disk
|
||||||
.OrderByDescending(drive => drive.RootDirectory.Length)
|
.OrderByDescending(drive => drive.RootDirectory.Length)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.DebugException(string.Format("Failed to get mount for path {0}", path), ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected List<IMount> GetDriveInfoMounts()
|
protected List<IMount> GetDriveInfoMounts()
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,10 +16,19 @@ namespace NzbDrone.Mono
|
||||||
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProvider));
|
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProvider));
|
||||||
|
|
||||||
private readonly IProcMountProvider _procMountProvider;
|
private readonly IProcMountProvider _procMountProvider;
|
||||||
|
private readonly ISymbolicLinkResolver _symLinkResolver;
|
||||||
|
|
||||||
public DiskProvider(IProcMountProvider procMountProvider)
|
public DiskProvider(IProcMountProvider procMountProvider, ISymbolicLinkResolver symLinkResolver)
|
||||||
{
|
{
|
||||||
_procMountProvider = procMountProvider;
|
_procMountProvider = procMountProvider;
|
||||||
|
_symLinkResolver = symLinkResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IMount GetMount(string path)
|
||||||
|
{
|
||||||
|
path = _symLinkResolver.GetCompleteRealPath(path);
|
||||||
|
|
||||||
|
return base.GetMount(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long? GetAvailableSpace(string path)
|
public override long? GetAvailableSpace(string path)
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
<Compile Include="ProcMount.cs" />
|
<Compile Include="ProcMount.cs" />
|
||||||
<Compile Include="ProcMountProvider.cs" />
|
<Compile Include="ProcMountProvider.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="SymbolicLinkResolver.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
|
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using Mono.Unix;
|
|
||||||
|
|
||||||
namespace NzbDrone.Mono
|
namespace NzbDrone.Mono
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using Mono.Unix;
|
||||||
|
using Mono.Unix.Native;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace NzbDrone.Mono
|
||||||
|
{
|
||||||
|
public interface ISymbolicLinkResolver
|
||||||
|
{
|
||||||
|
string GetCompleteRealPath(string path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono's own implementation doesn't handle exceptions very well.
|
||||||
|
// All of this code was copied from mono with minor changes.
|
||||||
|
public class SymbolicLinkResolver : ISymbolicLinkResolver
|
||||||
|
{
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public SymbolicLinkResolver(Logger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCompleteRealPath(string path)
|
||||||
|
{
|
||||||
|
if (path == null) return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] dirs;
|
||||||
|
int lastIndex;
|
||||||
|
GetPathComponents(path, out dirs, out lastIndex);
|
||||||
|
|
||||||
|
var realPath = new StringBuilder();
|
||||||
|
if (dirs.Length > 0)
|
||||||
|
{
|
||||||
|
var dir = UnixPath.IsPathRooted(path) ? "/" : "";
|
||||||
|
dir += dirs[0];
|
||||||
|
realPath.Append(GetRealPath(dir));
|
||||||
|
}
|
||||||
|
for (var i = 1; i < lastIndex; ++i)
|
||||||
|
{
|
||||||
|
realPath.Append("/").Append(dirs[i]);
|
||||||
|
var realSubPath = GetRealPath(realPath.ToString());
|
||||||
|
realPath.Remove(0, realPath.Length);
|
||||||
|
realPath.Append(realSubPath);
|
||||||
|
}
|
||||||
|
return realPath.ToString();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.DebugException(string.Format("Failed to check for symlinks in the path {0}", path), ex);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void GetPathComponents(string path, out string[] components, out int lastIndex)
|
||||||
|
{
|
||||||
|
var dirs = path.Split(UnixPath.DirectorySeparatorChar);
|
||||||
|
var target = 0;
|
||||||
|
for (var i = 0; i < dirs.Length; ++i)
|
||||||
|
{
|
||||||
|
if (dirs[i] == "." || dirs[i] == string.Empty)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirs[i] == "..")
|
||||||
|
{
|
||||||
|
if (target != 0)
|
||||||
|
{
|
||||||
|
target--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dirs[target++] = dirs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
components = dirs;
|
||||||
|
lastIndex = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetRealPath(string path)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var link = UnixPath.TryReadLink(path);
|
||||||
|
|
||||||
|
if (link == null)
|
||||||
|
{
|
||||||
|
var errno = Stdlib.GetLastError();
|
||||||
|
if (errno != Errno.EINVAL)
|
||||||
|
{
|
||||||
|
_logger.Trace("Checking path {0} for symlink returned error {1}, assuming it's not a symlink.", path, errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnixPath.IsPathRooted(link))
|
||||||
|
{
|
||||||
|
path = link;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = UnixPath.GetDirectoryName(path) + UnixPath.DirectorySeparatorChar + link;
|
||||||
|
path = UnixPath.GetCanonicalPath(path);
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue