diff --git a/src/NzbDrone.Common.Test/ExtensionTests/FromOctalStringFixture.cs b/src/NzbDrone.Common.Test/ExtensionTests/FromOctalStringFixture.cs new file mode 100644 index 000000000..5dcb12b94 --- /dev/null +++ b/src/NzbDrone.Common.Test/ExtensionTests/FromOctalStringFixture.cs @@ -0,0 +1,18 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Common.Extensions; + +namespace NzbDrone.Common.Test.ExtensionTests +{ + [TestFixture] + public class FromOctalStringFixture + { + [TestCase("\\040", " ")] + [TestCase("\\043", "#")] + [TestCase("\\101", "A")] + public void should_convert_octal_character_string_to_ascii_string(string octalString, string expected) + { + octalString.FromOctalString().Should().Be(expected); + } + } +} diff --git a/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj index 84892c6b1..a9215c217 100644 --- a/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj +++ b/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj @@ -79,6 +79,7 @@ + diff --git a/src/NzbDrone.Common/Disk/IMount.cs b/src/NzbDrone.Common/Disk/IMount.cs index 7e5ed499e..c3c1d71a4 100644 --- a/src/NzbDrone.Common/Disk/IMount.cs +++ b/src/NzbDrone.Common/Disk/IMount.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; namespace NzbDrone.Common.Disk { diff --git a/src/NzbDrone.Common/Extensions/StringExtensions.cs b/src/NzbDrone.Common/Extensions/StringExtensions.cs index e5bd84902..247274e29 100644 --- a/src/NzbDrone.Common/Extensions/StringExtensions.cs +++ b/src/NzbDrone.Common/Extensions/StringExtensions.cs @@ -105,5 +105,17 @@ public static string ToHexString(this byte[] input) { return string.Concat(Array.ConvertAll(input, x => x.ToString("X2"))); } + + public static string FromOctalString(this string octalValue) + { + octalValue = octalValue.TrimStart('\\'); + + var first = int.Parse(octalValue.Substring(0, 1)); + var second = int.Parse(octalValue.Substring(1, 1)); + var third = int.Parse(octalValue.Substring(2, 1)); + var byteResult = (byte)((first << 6) | (second << 3) | (third)); + + return Encoding.ASCII.GetString(new [] { byteResult }); + } } } \ No newline at end of file diff --git a/src/NzbDrone.Mono.Test/NzbDrone.Mono.Test.csproj b/src/NzbDrone.Mono.Test/NzbDrone.Mono.Test.csproj index 1c18d5e7a..a59d72c42 100644 --- a/src/NzbDrone.Mono.Test/NzbDrone.Mono.Test.csproj +++ b/src/NzbDrone.Mono.Test/NzbDrone.Mono.Test.csproj @@ -62,6 +62,10 @@ False ..\Libraries\Mono.Posix.dll + + ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll + True + ..\packages\NUnit.3.2.0\lib\net40\nunit.framework.dll True diff --git a/src/NzbDrone.Mono.Test/packages.config b/src/NzbDrone.Mono.Test/packages.config index d6c314b16..524708b50 100644 --- a/src/NzbDrone.Mono.Test/packages.config +++ b/src/NzbDrone.Mono.Test/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file diff --git a/src/NzbDrone.Mono/DiskProvider.cs b/src/NzbDrone.Mono/DiskProvider.cs index 742d00fbe..efd61679a 100644 --- a/src/NzbDrone.Mono/DiskProvider.cs +++ b/src/NzbDrone.Mono/DiskProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Mono.Unix; @@ -83,7 +84,7 @@ public override void SetPermissions(string path, string mask, string user, strin SetOwner(path, user, group); } - public override System.Collections.Generic.List GetMounts() + public override List GetMounts() { return base.GetMounts() .Concat(_procMountProvider.GetMounts()) diff --git a/src/NzbDrone.Mono/ProcMountProvider.cs b/src/NzbDrone.Mono/ProcMountProvider.cs index 08c2db7dd..3c695bc61 100644 --- a/src/NzbDrone.Mono/ProcMountProvider.cs +++ b/src/NzbDrone.Mono/ProcMountProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; @@ -17,6 +18,10 @@ public class ProcMountProvider : IProcMountProvider { private static string[] _fixedTypes = new [] { "ext3", "ext2", "ext4", "vfat", "fuseblk", "xfs", "jfs", "msdos", "ntfs", "minix", "hfs", "hfsplus", "qnx4", "ufs", "btrfs" }; private static string[] _networkDriveTypes = new [] { "cifs", "nfs", "nfs4", "nfsd", "sshfs" }; + private static readonly Regex OctalRegex = new Regex(@"\\\d{3}", RegexOptions.Compiled); + + private const string PROC_MOUNTS_FILENAME = @"/proc/mounts"; + private const string PROC_FILESYSTEMS_FILENAME = @"/proc/filesystems"; private static Dictionary _fileSystems; @@ -31,16 +36,16 @@ public List GetMounts() { try { - if (File.Exists(@"/proc/mounts")) + if (File.Exists(PROC_MOUNTS_FILENAME)) { - var lines = File.ReadAllLines(@"/proc/mounts"); + var lines = File.ReadAllLines(PROC_MOUNTS_FILENAME); return lines.Select(ParseLine).OfType().ToList(); } } catch (Exception ex) { - _logger.Debug(ex, "Failed to retrieve mounts from /proc/mounts"); + _logger.Debug(ex, "Failed to retrieve mounts from {0}", PROC_MOUNTS_FILENAME); } return new List(); @@ -53,9 +58,9 @@ private Dictionary GetFileSystems() var result = new Dictionary(); try { - if (File.Exists(@"/proc/filesystems")) + if (File.Exists(PROC_FILESYSTEMS_FILENAME)) { - var lines = File.ReadAllLines(@"/proc/filesystems"); + var lines = File.ReadAllLines(PROC_FILESYSTEMS_FILENAME); foreach (var line in lines) { @@ -67,7 +72,7 @@ private Dictionary GetFileSystems() } catch (Exception ex) { - _logger.Debug(ex, "Failed to get filesystem types from /proc/filesystems, using default set."); + _logger.Debug(ex, "Failed to get filesystem types from {0}, using default set.", PROC_FILESYSTEMS_FILENAME); } if (result.Empty()) @@ -86,11 +91,11 @@ private Dictionary GetFileSystems() private IMount ParseLine(string line) { - var split = line.Split(' '); + var split = line.Split(' ').Select(ExpandEscapes).ToArray(); if (split.Length != 6) { - _logger.Debug("Unable to parser /proc/mount line: {0}", line); + _logger.Debug("Unable to parse {0} line: {1}", PROC_MOUNTS_FILENAME, line); } var name = split[0]; @@ -132,5 +137,10 @@ private Dictionary ParseOptions(string options) return result; } + + private string ExpandEscapes(string mount) + { + return OctalRegex.Replace(mount, match => match.Captures[0].Value.FromOctalString()); + } } }