From 75378f7bde90b9d3d9b72404c25c017da2cd147c Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 16 Feb 2023 17:05:39 -0800 Subject: [PATCH] Fixed: USB drives mounted to folders are treated as different mounts Closes #4147 --- src/NzbDrone.Common/Disk/DiskProviderBase.cs | 2 +- src/NzbDrone.Windows/Disk/DiskProvider.cs | 34 ++++++++++++++++++ src/NzbDrone.Windows/Disk/FolderMount.cs | 38 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/NzbDrone.Windows/Disk/FolderMount.cs diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index 23f35981d..d4ead276e 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -339,7 +339,7 @@ public bool IsFileLocked(string file) } } - public string GetPathRoot(string path) + public virtual string GetPathRoot(string path) { Ensure.That(path, () => path).IsValidPath(); diff --git a/src/NzbDrone.Windows/Disk/DiskProvider.cs b/src/NzbDrone.Windows/Disk/DiskProvider.cs index d8b9dc448..3200e669b 100644 --- a/src/NzbDrone.Windows/Disk/DiskProvider.cs +++ b/src/NzbDrone.Windows/Disk/DiskProvider.cs @@ -26,6 +26,22 @@ private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); + public override IMount GetMount(string path) + { + var reparsePoint = GetReparsePoint(path); + + return reparsePoint ?? base.GetMount(path); + } + + public override string GetPathRoot(string path) + { + Ensure.That(path, () => path).IsValidPath(); + + var reparsePoint = GetReparsePoint(path); + + return reparsePoint?.RootDirectory ?? base.GetPathRoot(path); + } + public override long? GetAvailableSpace(string path) { Ensure.That(path, () => path).IsValidPath(); @@ -171,5 +187,23 @@ public override bool TryCreateHardLink(string source, string destination) return false; } } + + private IMount GetReparsePoint(string path) + { + var di = new DirectoryInfo(path); + var isReparsePoint = di.Attributes.HasFlag(FileAttributes.ReparsePoint); + + while (!isReparsePoint && (di = di.Parent) != null) + { + isReparsePoint = di.Attributes.HasFlag(FileAttributes.ReparsePoint); + } + + if (isReparsePoint) + { + return new FolderMount(di); + } + + return null; + } } } diff --git a/src/NzbDrone.Windows/Disk/FolderMount.cs b/src/NzbDrone.Windows/Disk/FolderMount.cs new file mode 100644 index 000000000..65fbcf5de --- /dev/null +++ b/src/NzbDrone.Windows/Disk/FolderMount.cs @@ -0,0 +1,38 @@ +using System.IO; +using NzbDrone.Common.Disk; +using NzbDrone.Common.Extensions; + +namespace NzbDrone.Windows.Disk +{ + public class FolderMount : IMount + { + private readonly DirectoryInfo _directoryInfo; + + public FolderMount(DirectoryInfo directoryInfo) + { + _directoryInfo = directoryInfo; + } + + public long AvailableFreeSpace => 0; + + public string DriveFormat => "NTFS"; + + public DriveType DriveType => DriveType.Removable; + + public bool IsReady => true; + + public MountOptions MountOptions { get; private set; } + + public string Name => _directoryInfo.Name; + + public string RootDirectory => _directoryInfo.FullName; + + public long TotalFreeSpace => 0; + + public long TotalSize => 0; + + public string VolumeLabel => _directoryInfo.Name; + + public string VolumeName => Name; + } +}