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();