diff --git a/build.ps1 b/build.ps1 index 639b28320..e7c323dcb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -27,6 +27,9 @@ Function Build() AddJsonNet + Write-Host "Removing Mono.Posix.dll" + Remove-Item "$outputFolder\Mono.Posix.dll" + Write-Host "##teamcity[progressFinish 'Build']" } diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index a6242f6ef..14ce5f4fa 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -1,12 +1,10 @@ using System; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; using NLog; using NzbDrone.Common.EnsureThat; -using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common.Disk @@ -23,7 +21,7 @@ namespace NzbDrone.Common.Disk public abstract long? GetAvailableSpace(string path); public abstract void InheritFolderPermissions(string filename); - public abstract void SetFilePermissions(string path, string mask); + public abstract void SetPermissions(string path, string mask); public abstract long? GetTotalSize(string path); public DateTime GetLastFolderWrite(string path) diff --git a/src/NzbDrone.Common/Disk/IDiskProvider.cs b/src/NzbDrone.Common/Disk/IDiskProvider.cs index a5a635dc2..5426c18db 100644 --- a/src/NzbDrone.Common/Disk/IDiskProvider.cs +++ b/src/NzbDrone.Common/Disk/IDiskProvider.cs @@ -13,6 +13,11 @@ namespace NzbDrone.Common.Disk { public interface IDiskProvider { + long? GetAvailableSpace(string path); + void InheritFolderPermissions(string filename); + void SetPermissions(string path, string mask); + long? GetTotalSize(string path); + DateTime GetLastFolderWrite(string path); DateTime GetLastFileWrite(string path); void EnsureFolder(string path); @@ -29,8 +34,6 @@ namespace NzbDrone.Common.Disk void DeleteFile(string path); void MoveFile(string source, string destination); void DeleteFolder(string path, bool recursive); - void InheritFolderPermissions(string filename); - long? GetAvailableSpace(string path); string ReadAllText(string filePath); void WriteAllText(string filename, string contents); void FileSetLastWriteTimeUtc(string path, DateTime dateTime); @@ -44,7 +47,6 @@ namespace NzbDrone.Common.Disk FileAttributes GetFileAttributes(string path); void EmptyFolder(string path); string[] GetFixedDrives(); - long? GetTotalSize(string path); string GetVolumeLabel(string path); } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index 3b66cad13..1427f998f 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -278,12 +278,26 @@ namespace NzbDrone.Core.Configuration set { SetValue("CreateEmptySeriesFolders", value); } } - public string DownloadClientWorkingFolders + public String DownloadClientWorkingFolders { get { return GetValue("DownloadClientWorkingFolders", "_UNPACK_|_FAILED_"); } set { SetValue("DownloadClientWorkingFolders", value); } } + public String FileChmod + { + get { return GetValue("FileChmod", "0755"); } + + set { SetValue("FileChmod", value); } + } + + public String FolderChmod + { + get { return GetValue("FolderChmod", "0755"); } + + set { SetValue("FolderChmod", value); } + } + private string GetValue(string key) { return GetValue(key, String.Empty); diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index 60f98aada..70982dedd 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -42,5 +42,7 @@ namespace NzbDrone.Core.Configuration Boolean EnableFailedDownloadHandling { get; set; } Boolean CreateEmptySeriesFolders { get; set; } void SaveValues(Dictionary configValues); + String FileChmod { get; set; } + String FolderChmod { get; set; } } } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index 60bd7ed13..626cdb020 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -6,7 +6,7 @@ using NzbDrone.Common; using NzbDrone.Common.Disk; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnvironmentInfo; -using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Organizer; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Tv; @@ -24,16 +24,19 @@ namespace NzbDrone.Core.MediaFiles private readonly IEpisodeService _episodeService; private readonly IBuildFileNames _buildFileNames; private readonly IDiskProvider _diskProvider; + private readonly IConfigService _configService; private readonly Logger _logger; public EpisodeFileMovingService(IEpisodeService episodeService, IBuildFileNames buildFileNames, IDiskProvider diskProvider, + IConfigService configService, Logger logger) { _episodeService = episodeService; _buildFileNames = buildFileNames; _diskProvider = diskProvider; + _configService = configService; _logger = logger; } @@ -85,6 +88,7 @@ namespace NzbDrone.Core.MediaFiles { _logger.Trace("Setting last write time on series folder: {0}", series.Path); _diskProvider.SetFolderWriteTime(series.Path, episodeFile.DateAdded); + SetFolderPermissions(series.Path); if (series.SeasonFolder) { @@ -92,6 +96,7 @@ namespace NzbDrone.Core.MediaFiles _logger.Trace("Setting last write time on season folder: {0}", seasonFolder); _diskProvider.SetFolderWriteTime(seasonFolder, episodeFile.DateAdded); + SetFolderPermissions(seasonFolder); } } @@ -122,6 +127,33 @@ namespace NzbDrone.Core.MediaFiles } } } + + else + { + SetPermissions(destinationFilename, _configService.FileChmod); + } + } + + private void SetPermissions(string path, string permissions) + { + try + { + _diskProvider.SetPermissions(path, permissions); + } + + catch (Exception ex) + { + if (ex is UnauthorizedAccessException || ex is InvalidOperationException) + { + _logger.Debug("Unable to apply permissions to: ", path); + _logger.TraceException(ex.Message, ex); + } + } + } + + private void SetFolderPermissions(string path) + { + SetPermissions(path, _configService.FolderChmod); } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs index b27b8e89d..ce9ee9ff5 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs @@ -1,5 +1,4 @@ using NLog; -using NzbDrone.Common; using NzbDrone.Common.Disk; using NzbDrone.Core.Parser.Model; diff --git a/src/NzbDrone.Core/MediaFiles/SetMediaFilePermissions.cs b/src/NzbDrone.Core/MediaFiles/SetMediaFilePermissions.cs new file mode 100644 index 000000000..1b379db76 --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/SetMediaFilePermissions.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Common.Disk; +using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Core.Configuration; + +namespace NzbDrone.Core.MediaFiles +{ + public interface ISetMediaFilePermissions + { + void SetPermissions(string filename); + } + + public class SetMediaFilePermissions : ISetMediaFilePermissions + { + private readonly IDiskProvider _diskProvider; + private readonly IConfigService _configService; + private readonly Logger _logger; + + public SetMediaFilePermissions(IDiskProvider diskProvider, IConfigService configService, Logger logger) + { + _diskProvider = diskProvider; + _configService = configService; + _logger = logger; + } + + public void SetPermissions(string filename) + { + if (OsInfo.IsWindows) + { + //Wrapped in Try/Catch to prevent this from causing issues with remote NAS boxes, the move worked, which is more important. + try + { + _diskProvider.InheritFolderPermissions(filename); + } + catch (Exception ex) + { + if (ex is UnauthorizedAccessException || ex is InvalidOperationException) + { + _logger.Debug("Unable to apply folder permissions to: ", filename); + _logger.TraceException(ex.Message, ex); + } + + else + { + throw; + } + } + } + + else + { + _diskProvider.SetPermissions(filename, _configService.FileChmod); + } + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 5dbf4fd48..894868c1c 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -290,6 +290,7 @@ + diff --git a/src/NzbDrone.Mono/DiskProvider.cs b/src/NzbDrone.Mono/DiskProvider.cs index 58c6f7d20..dedfe57b3 100644 --- a/src/NzbDrone.Mono/DiskProvider.cs +++ b/src/NzbDrone.Mono/DiskProvider.cs @@ -49,8 +49,10 @@ namespace NzbDrone.Mono } } - public override void SetFilePermissions(string path, string mask) + public override void SetPermissions(string path, string mask) { + Logger.Trace("Setting permissions: {0} on {1}", mask, path); + var filePermissions = NativeConvert.FromOctalPermissionString(mask); if (Syscall.chmod(path, filePermissions) < 0) diff --git a/src/NzbDrone.Windows/DiskProvider.cs b/src/NzbDrone.Windows/DiskProvider.cs index 27b9debc4..6eb2863f2 100644 --- a/src/NzbDrone.Windows/DiskProvider.cs +++ b/src/NzbDrone.Windows/DiskProvider.cs @@ -4,7 +4,6 @@ using System.Runtime.InteropServices; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnsureThat; -using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Instrumentation; namespace NzbDrone.Windows @@ -41,9 +40,9 @@ namespace NzbDrone.Windows File.SetAccessControl(filename, fs); } - public override void SetFilePermissions(string path, string mask) + public override void SetPermissions(string path, string mask) { - throw new NotImplementedException(); + } public override long? GetTotalSize(string path)