/// <inheritdoc /> public async Task <ServerSideModifications> CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); //just assume no other fs race conditions here var dmeExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, dmeFile), cancellationToken); var headFileExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, CodeModificationsHeadFile), cancellationToken); var tailFileExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, CodeModificationsTailFile), cancellationToken); var copyTask = ioManager.CopyDirectory(CodeModificationsSubdirectory, destination, null, cancellationToken); await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask).ConfigureAwait(false); if (!dmeExistsTask.Result && !headFileExistsTask.Result && !tailFileExistsTask.Result) { return(null); } if (dmeExistsTask.Result) { return(new ServerSideModifications(null, null, true)); } if (!headFileExistsTask.Result && !tailFileExistsTask.Result) { return(null); } string IncludeLine(string filePath) => String.Format(CultureInfo.InvariantCulture, "#include \"{0}\"", filePath); return(new ServerSideModifications(headFileExistsTask.Result ? IncludeLine(CodeModificationsHeadFile) : null, tailFileExistsTask.Result ? IncludeLine(CodeModificationsTailFile) : null, false)); } }
/// <inheritdoc /> public async Task <bool> HandleEvent(EventType eventType, IEnumerable <string> parameters, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); if (!EventTypeScriptFileNameMap.TryGetValue(eventType, out var scriptName)) { return(true); } //always execute in serial using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { var files = await ioManager.GetFilesWithExtension(EventScriptsSubdirectory, SystemScriptFileExtension, cancellationToken).ConfigureAwait(false); var resolvedScriptsDir = ioManager.ResolvePath(EventScriptsSubdirectory); foreach (var I in files.Select(x => ioManager.GetFileName(x)).Where(x => x.StartsWith(scriptName, StringComparison.Ordinal))) { using (var script = processExecutor.LaunchProcess(ioManager.ConcatPath(resolvedScriptsDir, I), resolvedScriptsDir, String.Join(' ', parameters), noShellExecute: true)) using (cancellationToken.Register(() => script.Terminate())) { var exitCode = await script.Lifetime.ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); if (exitCode != 0) { return(false); } } } } return(true); }
/// <inheritdoc /> public async Task <string> HandleChatCommand(string commandName, string arguments, Chat.User sender, CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { if (!Running) { return("ERROR: Server offline!"); } var commandObject = new ChatCommand { Command = commandName, Parameters = arguments, User = sender }; var json = JsonConvert.SerializeObject(commandObject, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); var command = String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChatCommand), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json)); var activeServer = AlphaIsActive ? alphaServer : bravoServer; return(await activeServer.SendCommand(command, cancellationToken).ConfigureAwait(false) ?? "ERROR: Bad topic exchange!"); } }
/// <inheritdoc /> public async Task <WatchdogLaunchResult> Restart(bool graceful, CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { if (!graceful || !Running) { Task chatTask; if (Running) { chatTask = chat.SendWatchdogMessage("Manual restart triggered...", cancellationToken); await TerminateNoLock(false, false, cancellationToken).ConfigureAwait(false); } else { chatTask = Task.CompletedTask; } var result = await LaunchNoLock(true, !Running, false, cancellationToken).ConfigureAwait(false); await chatTask.ConfigureAwait(false); return(result); } var toReboot = AlphaIsActive ? alphaServer : bravoServer; var other = AlphaIsActive ? bravoServer : alphaServer; if (toReboot != null) { if (!await toReboot.SetRebootState(Components.Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false)) { logger.LogWarning("Unable to send reboot state change event!"); } } return(null); } }
/// <inheritdoc /> public async Task ChangeVersion(Version version, Stream customVersionStream, CancellationToken cancellationToken) { if (version == null) { throw new ArgumentNullException(nameof(version)); } var versionKey = await InstallVersion(version, customVersionStream, cancellationToken).ConfigureAwait(false); using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false); await eventConsumer.HandleEvent( EventType.ByondActiveVersionChange, new List <string> { ActiveVersion != null ? VersionKey(ActiveVersion, true) : null, versionKey }, cancellationToken) .ConfigureAwait(false); // We reparse the version key because it could be changed after a custom install. ActiveVersion = Version.Parse(versionKey); } }
/// <inheritdoc /> public async Task TrustDmbPath(string fullDmbPath, CancellationToken cancellationToken) { if (fullDmbPath == null) { throw new ArgumentNullException(nameof(fullDmbPath)); } using (await SemaphoreSlimContext.Lock(trustedFileSemaphore, cancellationToken).ConfigureAwait(false)) { string trustedFileText; if (await ioManager.FileExists(trustedFilePath, cancellationToken).ConfigureAwait(false)) { var trustedFileBytes = await ioManager.ReadAllBytes(trustedFilePath, cancellationToken).ConfigureAwait(false); trustedFileText = Encoding.UTF8.GetString(trustedFileBytes); trustedFileText = $"{trustedFileText.Trim()}{Environment.NewLine}"; } else { trustedFileText = String.Empty; } if (trustedFileText.Contains(fullDmbPath, StringComparison.Ordinal)) { return; } trustedFileText = $"{trustedFileText}{fullDmbPath}{Environment.NewLine}"; var newTrustedFileBytes = Encoding.UTF8.GetBytes(trustedFileText); await ioManager.WriteAllBytes(trustedFilePath, newTrustedFileBytes, cancellationToken).ConfigureAwait(false); } }
/// <inheritdoc /> public async Task <bool> ApplyUpdate(byte[] updateZipData, IIOManager ioManager, CancellationToken cancellationToken) { if (updatePath == null) { return(false); } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { if (updated) { throw new InvalidOperationException("ApplyUpdate has already been called!"); } updated = true; try { await ioManager.ZipToDirectory(updatePath, updateZipData, cancellationToken).ConfigureAwait(false); } catch { try { //important to not leave this directory around if possible await ioManager.DeleteDirectory(updatePath, default).ConfigureAwait(false); } catch { } updated = false; throw; } Restart(); return(true); } }
/// <inheritdoc /> public async Task Restart(bool graceful, CancellationToken cancellationToken) { Logger.LogTrace("Begin Restart. Graceful: {0}", graceful); using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false)) { if (!graceful || !Running) { Task chatTask; if (Running) { chatTask = Chat.SendWatchdogMessage("Manual restart triggered...", cancellationToken); await TerminateNoLock(false, false, cancellationToken).ConfigureAwait(false); } else { chatTask = Task.CompletedTask; } await LaunchImplNoLock(true, !Running, null, cancellationToken).ConfigureAwait(false); await chatTask.ConfigureAwait(false); } var toReboot = GetActiveController(); if (toReboot != null) { if (!await toReboot.SetRebootState(Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false)) { Logger.LogWarning("Unable to send reboot state change event!"); } } } }
/// <inheritdoc /> public async Task SetChannels(IEnumerable <Channel> channels, CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(channelsSemaphore, cancellationToken).ConfigureAwait(false)) await ioManager.WriteAllBytes(channelsPath, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(channels, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() })), cancellationToken).ConfigureAwait(false); }
/// <inheritdoc /> public async Task Initialize(CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { if (modulesAndEnabledStatus != null) { return; } modulesAndEnabledStatus = new Dictionary <IModule, bool>(); var tasks = new List <Task <IModule> >(); async Task <KeyValuePair <IModule, bool> > InitPlugin(IModule plugin) { var type = plugin.GetType(); logger.LogTrace("Plugin {0}.Name: {1}", type, plugin.Name); logger.LogTrace("Plugin {0}.Description: {1}", type, plugin.Description); logger.LogTrace("Plugin {0}.Uid: {1}", type, plugin.Uid); var query = databaseContext.ModuleMetadatas.Where(x => x.Id == plugin.Uid); var result = await query.ToAsyncEnumerable().FirstOrDefault().ConfigureAwait(false); bool enabled; if (result == default(ModuleMetadata)) { enabled = true; await databaseContext.ModuleMetadatas.AddAsync(new ModuleMetadata { Id = plugin.Uid, Enabled = true }).ConfigureAwait(false); } else { enabled = result.Enabled; } logger.LogTrace("Plugin {0}.Enabled: {1}", type, enabled); return(new KeyValuePair <IModule, bool>(plugin, enabled)); }; using (logger.BeginScope("Loading plugins...")) { var tasks2 = new List <Task <KeyValuePair <IModule, bool> > >(); tasks2.AddRange(allModules.Select(x => InitPlugin(x))); await Task.WhenAll(tasks2).ConfigureAwait(false); await databaseContext.Save(cancellationToken).ConfigureAwait(false); foreach (var I in tasks2.Select(x => x.Result)) { modulesAndEnabledStatus.Add(I); I.Key.SetEnabled(I.Value); } } } }
/// <inheritdoc /> public async Task DeleteRepository(CancellationToken cancellationToken) { logger.LogInformation("Deleting repository..."); using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { logger.LogTrace("Semaphore acquired, deleting Repository directory..."); await ioManager.DeleteDirectory(ioManager.ResolvePath(), cancellationToken).ConfigureAwait(false); } }
/// <inheritdoc /> public async Task ChangeVersion(Version version, CancellationToken cancellationToken) { await InstallVersion(version, cancellationToken).ConfigureAwait(false); using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false); ActiveVersion = version; } }
/// <inheritdoc /> public async Task <bool> HandleEvent(EventType eventType, IEnumerable <string> parameters, CancellationToken cancellationToken) { if (!Running) { return(true); } string results; using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false)) { if (!Running) { return(true); } var builder = new StringBuilder(Constants.DMTopicEvent); builder.Append('&'); var notification = new EventNotification { Type = eventType, Parameters = parameters }; var json = JsonConvert.SerializeObject(notification); builder.Append(byondTopicSender.SanitizeString(Constants.DMParameterData)); builder.Append('='); builder.Append(byondTopicSender.SanitizeString(json)); var activeServer = GetActiveController(); results = await activeServer.SendCommand(builder.ToString(), cancellationToken).ConfigureAwait(false); } if (results == Constants.DMResponseSuccess) { return(true); } List <Response> responses; try { responses = JsonConvert.DeserializeObject <List <Response> >(results); } catch { Logger.LogInformation("Recieved invalid response from DD when parsing event {0}:{1}{2}", eventType, Environment.NewLine, results); return(true); } await Task.WhenAll(responses.Select(x => Chat.SendMessage(x.Message, x.ChannelIds, cancellationToken))).ConfigureAwait(false); return(true); }
/// <inheritdoc /> public async Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { ActiveLaunchParameters = launchParameters; if (Running) { //queue an update activeParametersUpdated.TrySetResult(null); } } }
/// <inheritdoc /> public override async Task InstallByond(string path, Version version, CancellationToken cancellationToken) { async Task SetNoPromptTrusted() { var configPath = IOManager.ConcatPath(path, ByondConfigDir); await IOManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false); await IOManager.WriteAllBytes(IOManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false); } var setNoPromptTrustedModeTask = SetNoPromptTrusted(); // after this version lummox made DD depend of directx lol // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/ // then he readded it again so -_- if (!installedDirectX) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (!installedDirectX) { // ^check again because race conditions // always install it, it's pretty fast and will do better redundancy checking than us var rbdx = IOManager.ConcatPath(path, ByondDXDir); // noShellExecute because we aren't doing runas shennanigans IProcess directXInstaller; try { directXInstaller = processExecutor.LaunchProcess(IOManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true); } catch (Exception e) { throw new JobException("Unable to start DirectX installer process! Is the server running with admin privileges?", e); } using (directXInstaller) { int exitCode; using (cancellationToken.Register(() => directXInstaller.Terminate())) exitCode = await directXInstaller.Lifetime.ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); if (exitCode != 0) { throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode)); } installedDirectX = true; } } } await setNoPromptTrustedModeTask.ConfigureAwait(false); }
/// <inheritdoc /> public async Task <IReadOnlyList <ConfigurationFile> > ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); var path = ValidateConfigRelativePath(configurationRelativePath); if (configurationRelativePath == null) { configurationRelativePath = "/"; } List <ConfigurationFile> result = new List <ConfigurationFile>(); void ListImpl() { var enumerator = synchronousIOManager.GetDirectories(path, cancellationToken); try { result.AddRange(enumerator.Select(x => new ConfigurationFile { IsDirectory = true, Path = ioManager.ConcatPath(configurationRelativePath, x), }).OrderBy(file => file.Path)); } catch (IOException e) { logger.LogDebug("IOException while writing {0}: {1}", path, e); result = null; return; } enumerator = synchronousIOManager.GetFiles(path, cancellationToken); result.AddRange(enumerator.Select(x => new ConfigurationFile { IsDirectory = false, Path = ioManager.ConcatPath(configurationRelativePath, x), }).OrderBy(file => file.Path)); } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (systemIdentity == null) { ListImpl(); } else { await systemIdentity.RunImpersonated(ListImpl, cancellationToken).ConfigureAwait(false); } return(result); }
/// <summary> /// Sets <see cref="knownUser"/> if it is <see langword="null"/> /// </summary> /// <returns>A <see cref="Task"/> representing the running operation</returns> async Task CheckUser(bool doLock, CancellationToken cancellationToken) { if (!doLock) { if (knownUser == null) { knownUser = await gitHubClient.User.Current().ConfigureAwait(false); } return; } using (SemaphoreSlimContext.Lock(semaphore, cancellationToken)) await CheckUser(false, cancellationToken).ConfigureAwait(false); }
/// <inheritdoc /> public async Task <bool> ApplyUpdate(Version version, byte[] updateZipData, IIOManager ioManager, CancellationToken cancellationToken) { if (version == null) { throw new ArgumentNullException(nameof(version)); } if (updateZipData == null) { throw new ArgumentNullException(nameof(updateZipData)); } if (ioManager == null) { throw new ArgumentNullException(nameof(ioManager)); } if (updatePath == null) { return(false); } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { if (updated) { throw new InvalidOperationException("ApplyUpdate has already been called!"); } updated = true; try { await ioManager.ZipToDirectory(updatePath, updateZipData, cancellationToken).ConfigureAwait(false); } catch (Exception e) { updated = false; try { //important to not leave this directory around if possible await ioManager.DeleteDirectory(updatePath, default).ConfigureAwait(false); } catch (Exception e2) { throw new AggregateException(e, e2); } throw; } await Restart(version).ConfigureAwait(false); return(true); } }
/// <inheritdoc /> public async Task ResetRebootState(CancellationToken cancellationToken) { using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false)) { if (!Running) { return; } var toClear = GetActiveController(); if (toClear != null) { toClear.ResetRebootState(); } } }
/// <inheritdoc /> public async Task <User> GetUserLogin(string accessToken, CancellationToken cancellationToken) { logger.LogTrace("GetUserLogin. accessToken: {0}", accessToken); if (accessToken == null) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await CheckUser(false, cancellationToken).ConfigureAwait(false); return(knownUser); } } return(await gitHubClientFactory.CreateGitHubClient(accessToken).User.Current().ConfigureAwait(false)); }
/// <inheritdoc /> public async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken) { async Task SymlinkBase(bool files) { Task <IReadOnlyList <string> > task; if (files) { task = ioManager.GetFiles(GameStaticFilesSubdirectory, cancellationToken); } else { task = ioManager.GetDirectories(GameStaticFilesSubdirectory, cancellationToken); } var entries = await task.ConfigureAwait(false); await Task.WhenAll(task.Result.Select(async x => { var destPath = ioManager.ConcatPath(destination, ioManager.GetFileName(x)); logger.LogTrace("Symlinking {0} to {1}...", x, destPath); var fileExistsTask = ioManager.FileExists(destPath, cancellationToken); if (await ioManager.DirectoryExists(destPath, cancellationToken).ConfigureAwait(false)) { await ioManager.DeleteDirectory(destPath, cancellationToken).ConfigureAwait(false); } var fileExists = await fileExistsTask.ConfigureAwait(false); if (fileExists) { await ioManager.DeleteFile(destPath, cancellationToken).ConfigureAwait(false); } await symlinkFactory.CreateSymbolicLink(ioManager.ResolvePath(x), ioManager.ResolvePath(destPath), cancellationToken).ConfigureAwait(false); })).ConfigureAwait(false); } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); await Task.WhenAll(SymlinkBase(true), SymlinkBase(false)).ConfigureAwait(false); } }
/// <inheritdoc /> public async Task ChangeVersion(Version version, CancellationToken cancellationToken) { if (version == null) { throw new ArgumentNullException(nameof(version)); } var versionKey = VersionKey(version); await InstallVersion(version, cancellationToken).ConfigureAwait(false); using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false); await eventConsumer.HandleEvent(EventType.ByondActiveVersionChange, new List <string> { ActiveVersion != null ? VersionKey(ActiveVersion) : null, versionKey }, cancellationToken).ConfigureAwait(false); ActiveVersion = version; } }
/// <summary> /// Attempt to install the DirectX redistributable included with BYOND. /// </summary> /// <param name="path">The path to the BYOND installation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param> /// <returns>A <see cref="Task"/> representing the running operation.</returns> async Task InstallDirectX(string path, CancellationToken cancellationToken) { using var lockContext = await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false); if (installedDirectX) { Logger.LogTrace("DirectX already installed."); return; } Logger.LogTrace("Installing DirectX redistributable..."); // always install it, it's pretty fast and will do better redundancy checking than us var rbdx = IOManager.ConcatPath(path, ByondDXDir); try { // noShellExecute because we aren't doing runas shennanigans using var directXInstaller = processExecutor.LaunchProcess( IOManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true); int exitCode; using (cancellationToken.Register(() => directXInstaller.Terminate())) exitCode = await directXInstaller.Lifetime.ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); if (exitCode != 0) { throw new JobException(ErrorCode.ByondDirectXInstallFail, new JobException($"Invalid exit code: {exitCode}")); } installedDirectX = true; } catch (Exception e) { throw new JobException(ErrorCode.ByondDirectXInstallFail, e); } }
/// <inheritdoc /> public async Task InstallByond(string path, Version version, CancellationToken cancellationToken) { async Task SetNoPromptTrusted() { var configPath = ioManager.ConcatPath(path, ByondConfigDir); await ioManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false); await ioManager.WriteAllBytes(ioManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false); }; var setNoPromptTrustedModeTask = SetNoPromptTrusted(); //after this version lummox made DD depend of directx lol if (version.Major >= 512 && version.Minor >= 1427 && !installedDirectX) { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (!installedDirectX) { //always install it, it's pretty fast and will do better redundancy checking than us var rbdx = ioManager.ConcatPath(path, ByondDXDir); //noShellExecute because we aren't doing runas shennanigans using (var p = processExecutor.LaunchProcess(ioManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true)) { int exitCode; using (cancellationToken.Register(() => p.Terminate())) exitCode = await p.Lifetime.ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); if (exitCode != 0) { throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode)); } installedDirectX = true; } } } await setNoPromptTrustedModeTask.ConfigureAwait(false); }
/// <inheritdoc /> public async Task <bool> CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); var path = ValidateConfigRelativePath(configurationRelativePath); bool?result = null; void DoCreate() => result = synchronousIOManager.CreateDirectory(path, cancellationToken); using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (systemIdentity == null) { await Task.Factory.StartNew(DoCreate, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); } else { await systemIdentity.RunImpersonated(DoCreate, cancellationToken).ConfigureAwait(false); } return(result.Value); }
/// <inheritdoc /> public async Task <bool> DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); var path = ValidateConfigRelativePath(configurationRelativePath); var result = false; using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { void CheckDeleteImpl() => result = synchronousIOManager.DeleteDirectory(path); if (systemIdentity != null) { await systemIdentity.RunImpersonated(CheckDeleteImpl, cancellationToken).ConfigureAwait(false); } else { CheckDeleteImpl(); } } return(result); }
/// <inheritdoc /> public async Task StartAsync(CancellationToken cancellationToken) { var reattachInfo = await reattachInfoHandler.Load(cancellationToken).ConfigureAwait(false); if (!autoStart && reattachInfo == null) { return; } long?adminUserId = null; await databaseContextFactory.UseContext(async db => adminUserId = await db.Users .Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant()) .Select(x => x.Id) .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); var job = new Models.Job { StartedBy = new Models.User { Id = adminUserId.Value }, Instance = new Models.Instance { Id = instance.Id }, Description = "Instance startup watchdog launch", CancelRight = (ulong)DreamDaemonRights.Shutdown, CancelRightsType = RightsType.DreamDaemon }; await jobManager.RegisterOperation(job, async (j, databaseContext, progressFunction, ct) => { using (await SemaphoreSlimContext.Lock(Semaphore, ct).ConfigureAwait(false)) await LaunchImplNoLock(true, true, reattachInfo, ct).ConfigureAwait(false); }, cancellationToken).ConfigureAwait(false); }
/// <inheritdoc /> public async Task <ConfigurationFile> Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); var path = ValidateConfigRelativePath(configurationRelativePath); ConfigurationFile result = null; void WriteImpl() { lock (this) try { var fileHash = previousHash; var success = synchronousIOManager.WriteFileChecked(path, data, ref fileHash, cancellationToken); if (!success) { return; } result = new ConfigurationFile { Content = data, IsDirectory = false, LastReadHash = fileHash, AccessDenied = false, Path = configurationRelativePath }; } catch (UnauthorizedAccessException) { //this happens on windows, dunno about linux bool isDirectory; try { isDirectory = synchronousIOManager.IsDirectory(path); } catch { isDirectory = false; } result = new ConfigurationFile { Path = configurationRelativePath }; if (!isDirectory) { result.AccessDenied = true; } else { result.IsDirectory = true; } } } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (systemIdentity == null) { await Task.Factory.StartNew(WriteImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); } else { await systemIdentity.RunImpersonated(WriteImpl, cancellationToken).ConfigureAwait(false); } return(result); }
/// <inheritdoc /> public async Task <IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action <int> progressReporter, CancellationToken cancellationToken) { lock (this) { if (CloneInProgress) { throw new InvalidOperationException("The repository is already being cloned!"); } CloneInProgress = true; } try { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false)) { try { await Task.Factory.StartNew(() => { string path = null; try { path = LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath("."), new CloneOptions { OnProgress = (a) => !cancellationToken.IsCancellationRequested, OnTransferProgress = (a) => { var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2)); progressReporter((int)percentage); return(!cancellationToken.IsCancellationRequested); }, RecurseSubmodules = true, OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested, RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested, BranchName = initialBranch, CredentialsProvider = (a, b, c) => username != null ? (Credentials) new UsernamePasswordCredentials { Username = username, Password = password } : new DefaultCredentials() }); } catch (UserCancelledException) { } cancellationToken.ThrowIfCancellationRequested(); }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); } catch { try { await ioManager.DeleteDirectory(".", default).ConfigureAwait(false); } catch { } throw; } } else { return(null); } } finally { CloneInProgress = false; } return(await LoadRepository(cancellationToken).ConfigureAwait(false)); }
/// <inheritdoc /> public async Task <ConfigurationFile> Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); var path = ValidateConfigRelativePath(configurationRelativePath); ConfigurationFile result = null; void ReadImpl() { lock (this) try { var content = synchronousIOManager.ReadFile(path); string sha1String; #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1. using (var sha1 = new SHA1Managed()) #pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1. sha1String = String.Join("", sha1.ComputeHash(content).Select(b => b.ToString("x2", CultureInfo.InvariantCulture))); result = new ConfigurationFile { Content = content, IsDirectory = false, LastReadHash = sha1String, AccessDenied = false, Path = configurationRelativePath }; } catch (UnauthorizedAccessException) { //this happens on windows, dunno about linux bool isDirectory; try { isDirectory = synchronousIOManager.IsDirectory(path); } catch { isDirectory = false; } result = new ConfigurationFile { Path = configurationRelativePath }; if (!isDirectory) { result.AccessDenied = true; } else { result.IsDirectory = true; } } } using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) if (systemIdentity == null) { await Task.Factory.StartNew(ReadImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); } else { await systemIdentity.RunImpersonated(ReadImpl, cancellationToken).ConfigureAwait(false); } return(result); }