diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index da99e976e7..3d136dd405 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -77,6 +77,11 @@ namespace Tgstation.Server.Host.Components /// readonly IProcessExecutor processExecutor; + /// + /// The for the + /// + readonly IPostWriteHandler postWriteHandler; + /// /// Construct an /// @@ -92,7 +97,8 @@ namespace Tgstation.Server.Host.Components /// The value of /// The value of /// The value of - public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, IServerControl serverUpdater, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IProviderFactory providerFactory, IProcessExecutor processExecutor) + /// The value of + public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, IServerControl serverUpdater, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IProviderFactory providerFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); @@ -106,6 +112,7 @@ namespace Tgstation.Server.Host.Components this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller)); this.providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory)); this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); + this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); } /// @@ -120,7 +127,7 @@ namespace Tgstation.Server.Host.Components var gameIoManager = new ResolvingIOManager(instanceIoManager, "Game"); var configurationIoManager = new ResolvingIOManager(instanceIoManager, "Configuration"); - var configuration = new StaticFiles.Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, processExecutor, loggerFactory.CreateLogger()); + var configuration = new StaticFiles.Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, processExecutor, postWriteHandler, loggerFactory.CreateLogger()); var eventConsumer = new EventConsumer(configuration); var dmbFactory = new DmbFactory(databaseContextFactory, gameIoManager, loggerFactory.CreateLogger(), metadata.CloneMetadata()); diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index d679f0b155..9a874b912f 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -54,6 +54,11 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// readonly IProcessExecutor processExecutor; + /// + /// The for + /// + readonly IPostWriteHandler postWriteHandler; + /// /// The for /// @@ -71,13 +76,15 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// The value of /// The value of /// The value of + /// The value of /// The value of - public Configuration(IIOManager ioManager, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IProcessExecutor processExecutor, ILogger logger) + public Configuration(IIOManager ioManager, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, ILogger logger) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager)); this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory)); this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); + this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); semaphore = new SemaphoreSlim(1); @@ -259,6 +266,8 @@ namespace Tgstation.Server.Host.Components.StaticFiles var success = synchronousIOManager.WriteFileChecked(path, data, previousHash, cancellationToken); if (!success) return; + if (data != null) + postWriteHandler.HandleWrite(path); string sha1String; #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1. using (var sha1 = new SHA1Managed()) diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/IPostWriteHandler.cs b/src/Tgstation.Server.Host/Components/StaticFiles/IPostWriteHandler.cs new file mode 100644 index 0000000000..e406cfa665 --- /dev/null +++ b/src/Tgstation.Server.Host/Components/StaticFiles/IPostWriteHandler.cs @@ -0,0 +1,11 @@ +namespace Tgstation.Server.Host.Components.StaticFiles +{ + interface IPostWriteHandler + { + /// + /// For handling system specific necessities after a write + /// + /// The full path to the file that was written + void HandleWrite(string filePath); + } +} diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/PosixPostWriteHandler.cs b/src/Tgstation.Server.Host/Components/StaticFiles/PosixPostWriteHandler.cs new file mode 100644 index 0000000000..90541a5174 --- /dev/null +++ b/src/Tgstation.Server.Host/Components/StaticFiles/PosixPostWriteHandler.cs @@ -0,0 +1,25 @@ +using Mono.Unix; +using Mono.Unix.Native; + +namespace Tgstation.Server.Host.Components.StaticFiles +{ + /// + /// for POSIX systems + /// + sealed class PosixPostWriteHandler : IPostWriteHandler + { + /// + public void HandleWrite(string filePath) + { + //set executable bit every time, don't want people calling me when their uploaded "sl" binary doesn't work + if (Syscall.stat(filePath, out var stat) != 0) + throw new UnixIOException(Stdlib.GetLastError()); + + if (stat.st_mode.HasFlag(FilePermissions.S_IXUSR)) + return; + + if(Syscall.chmod(filePath, stat.st_mode | FilePermissions.S_IXUSR) != 0) + throw new UnixIOException(Stdlib.GetLastError()); + } + } +} diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/WindowsPostWriteHandler.cs b/src/Tgstation.Server.Host/Components/StaticFiles/WindowsPostWriteHandler.cs new file mode 100644 index 0000000000..61c8431662 --- /dev/null +++ b/src/Tgstation.Server.Host/Components/StaticFiles/WindowsPostWriteHandler.cs @@ -0,0 +1,11 @@ +namespace Tgstation.Server.Host.Components.StaticFiles +{ + /// + /// for Windows systems + /// + sealed class WindowsPostWriteHandler : IPostWriteHandler + { + /// + public void HandleWrite(string filePath) { } + } +} diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index 17149ce438..e7b4805557 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -190,12 +190,14 @@ namespace Tgstation.Server.Host.Core services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); } else { services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); } services.AddSingleton();