diff --git a/src/NzbDrone.Mono/Disk/DiskProvider.cs b/src/NzbDrone.Mono/Disk/DiskProvider.cs index cc3440aa9..df58608b8 100644 --- a/src/NzbDrone.Mono/Disk/DiskProvider.cs +++ b/src/NzbDrone.Mono/Disk/DiskProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using Mono.Unix; using Mono.Unix.Native; using NLog; @@ -33,11 +34,35 @@ namespace NzbDrone.Mono.Disk public override IMount GetMount(string path) { - path = _symLinkResolver.GetCompletePath(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); + } + path = realPath.ToString(); + } + catch (Exception ex) + { + _logger.Debug(ex, string.Format("Failed to check for symlinks in the path {0}", path)); + } - _logger.Warn("Testing 123: {0}, {1}", _symLinkResolver, _symLinkResolver.GetType()); - _logger.Debug("Testing"); - Console.WriteLine($"Testing 123: {_symLinkResolver}, {_symLinkResolver.GetType()}"); return base.GetMount(path); } @@ -224,5 +249,65 @@ namespace NzbDrone.Mono.Disk } + + 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); + } } }