Merge pull request #7717 from spycrab/macos_updater

Implement MacOS Updater
This commit is contained in:
spycrab
2019-02-06 22:21:30 +01:00
committed by GitHub
15 changed files with 1335 additions and 12 deletions
+5
View File
@@ -587,6 +587,11 @@ else()
set(PNG png)
endif()
if (APPLE)
message(STATUS "Using ed25519 from Externals")
add_subdirectory(Externals/ed25519)
endif()
# Using static soundtouch from Externals
# Unable to use system soundtouch library: We require shorts, not floats.
add_subdirectory(Externals/soundtouch)
+13
View File
@@ -0,0 +1,13 @@
project(ed25519 C)
add_library(ed25519
add_scalar.c
ge.c
keypair.c
seed.c
sign.c
fe.c
key_exchange.c
sc.c
sha512.c
verify.c)
+4
View File
@@ -11,3 +11,7 @@ add_subdirectory(VideoBackends)
if(ENABLE_QT)
add_subdirectory(DolphinQt)
endif()
if (APPLE)
add_subdirectory(MacUpdater)
endif()
+4
View File
@@ -42,6 +42,7 @@
#include <CoreFoundation/CFBundle.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFURL.h>
#include <mach-o/dyld.h>
#include <sys/param.h>
#endif
@@ -683,6 +684,9 @@ std::string GetExePath()
dolphin_path = TStrToUTF8(dolphin_exe_expanded_path);
else
dolphin_path = TStrToUTF8(dolphin_exe_path);
#elif defined(__APPLE__)
dolphin_path = GetBundleDirectory();
dolphin_path = dolphin_path.substr(0, dolphin_path.find_last_of("Dolphin.app/Contents/MacOS"));
#else
char dolphin_exe_path[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", dolphin_exe_path, sizeof(dolphin_exe_path));
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
set(STORYBOARDS Main.storyboard)
set(SOURCES
main.m
AppDelegate.h
AppDelegate.mm
ViewController.h
ViewController.m
UI.h
UI.mm
${STORYBOARDS}
)
add_executable(MacUpdater ${SOURCES})
set(MacUpdater_NAME "Dolphin Updater")
set_target_properties(MacUpdater PROPERTIES
MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
OUTPUT_NAME ${MacUpdater_NAME})
target_compile_options(MacUpdater PRIVATE -x objective-c++)
# Copy icon into the bundle
target_sources(MacUpdater PRIVATE "${CMAKE_SOURCE_DIR}/Data/Dolphin.icns")
set_source_files_properties("${CMAKE_SOURCE_DIR}/Data/Dolphin.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
target_link_libraries(MacUpdater PRIVATE
"-framework Cocoa"
"-framework AppKit"
"-framework CoreData"
"-framework Foundation"
uicommon
mbedtls
z
ed25519
)
# Compile storyboards (Adapted from https://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/OSX-InterfaceBuilderFiles)
# Make sure we can find the 'ibtool' program. If we can NOT find it we
# skip generation of this project
find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND")
message(SEND_ERROR "ibtool can not be found and is needed to compile the .storyboard files. It should have been installed with
the Apple developer tools. The default system paths were searched in addition to ${OSX_DEVELOPER_ROOT}/usr/bin")
endif()
foreach(sb ${STORYBOARDS})
set(MacUpdater_BIN_DIR ${CMAKE_BINARY_DIR}/Binaries)
if (CMAKE_GENERATOR STREQUAL Xcode)
string(APPEND MacUpdater_BIN_DIR "/\${CONFIGURATION}")
endif()
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
--compile ${MacUpdater_BIN_DIR}/${MacUpdater_NAME}.app/Contents/Resources/${sb}c
${CMAKE_CURRENT_SOURCE_DIR}/${sb}
COMMENT "Compiling Storyboard ${sb}...")
endforeach()
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MacUpdater_NAME}</string>
<key>CFBundleIconFile</key>
<string>Dolphin.icns</string>
<key>CFBundleIdentifier</key>
<string>com.dolphinteam.dolphin-updater</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Updater</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
<key>NSHumanReadableCopyright</key>
<string>Licensed under GPL version 2 or later (GPLv2+)</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
+109
View File
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment version="101000" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Updater" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Updater" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About Updater" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Quit Updater" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="Dolphin Updater" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="480" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<progressIndicator identifier="progressTotal" wantsLayer="YES" fixedFrame="YES" maxValue="100" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="oLS-AW-V72">
<rect key="frame" x="20" y="81" width="440" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
<progressIndicator identifier="progressCurrent" wantsLayer="YES" fixedFrame="YES" maxValue="100" indeterminate="YES" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="mni-rL-166">
<rect key="frame" x="20" y="39" width="440" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
<textField identifier="labelProgress" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r87-pn-Exw" userLabel="Label">
<rect key="frame" x="18" y="15" width="444" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Initializing..." id="FBK-Tz-5cA">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="progressLabel:" target="XfG-lQ-9wD" id="PDs-H5-idS"/>
</connections>
</textField>
</subviews>
</view>
<connections>
<outlet property="foo" destination="r87-pn-Exw" id="i76-Sg-K3o"/>
<outlet property="labelProgress" destination="r87-pn-Exw" id="v6b-r7-3lR"/>
<outlet property="progressCurrent" destination="mni-rL-166" id="A3C-wp-83j"/>
<outlet property="progressTotal" destination="oLS-AW-V72" id="pwo-CZ-XyN"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="647"/>
</scene>
</scenes>
</document>
+24
View File
@@ -0,0 +1,24 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
namespace UI
{
void Error(const std::string& text);
void SetVisible(bool visible);
void SetDescription(const std::string& text);
void SetTotalMarquee(bool marquee);
void ResetTotalProgress();
void SetTotalProgress(int current, int total);
void SetCurrentMarquee(bool marquee);
void ResetCurrentProgress();
void SetCurrentProgress(int current, int total);
} // namespace UI
+107
View File
@@ -0,0 +1,107 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "MacUpdater/UI.h"
#include "MacUpdater/ViewController.h"
#include <Cocoa/Cocoa.h>
#include <functional>
// When we call from the main thread, we are not allowed to use
// dispatch_sync(dispatch_get_main_queue() as it will cause crashes) To prevent this check if we're
// already on the main thread first
void run_on_main(std::function<void()> fnc)
{
if (![NSThread isMainThread])
{
dispatch_sync(dispatch_get_main_queue(), ^{
fnc();
});
}
else
{
fnc();
}
}
NSWindow* GetWindow()
{
return [[[NSApplication sharedApplication] windows] objectAtIndex:0];
}
ViewController* GetView()
{
return (ViewController*)GetWindow().contentViewController;
}
void UI::Error(const std::string& text)
{
run_on_main([&] {
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Fatal error"];
[alert
setInformativeText:[NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding]];
[alert setAlertStyle:NSAlertStyleCritical];
[alert beginSheetModalForWindow:GetWindow()
completionHandler:^(NSModalResponse) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}];
});
}
void UI::SetVisible(bool visible)
{
run_on_main([&] {
if (visible)
{
[NSApp unhide:nil];
[NSApp activateIgnoringOtherApps:YES];
}
else
{
[NSApp hide:nil];
}
});
}
void UI::SetDescription(const std::string& text)
{
run_on_main([&] {
[GetView()
SetDescription:[NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding]];
});
}
void UI::SetTotalMarquee(bool marquee)
{
run_on_main([marquee] { [GetView() SetTotalMarquee:marquee]; });
}
void UI::SetCurrentMarquee(bool marquee)
{
run_on_main([&] { [GetView() SetCurrentMarquee:marquee]; });
}
void UI::ResetTotalProgress()
{
run_on_main([] { SetTotalProgress(0, 1); });
}
void UI::ResetCurrentProgress()
{
run_on_main([] { SetCurrentProgress(0, 1); });
}
void UI::SetCurrentProgress(int current, int total)
{
run_on_main([&] { [GetView() SetCurrentProgress:(double)current total:(double)total]; });
}
void UI::SetTotalProgress(int current, int total)
{
run_on_main([&] { [GetView() SetTotalProgress:(double)current total:(double)total]; });
}
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import <Cocoa/Cocoa.h>
@interface ViewController : NSViewController
@property(assign) IBOutlet NSProgressIndicator* progressCurrent;
@property(assign) IBOutlet NSProgressIndicator* progressTotal;
@property(assign) IBOutlet NSTextField* labelProgress;
- (void)SetDescription:(NSString*)string;
- (void)SetTotalMarquee:(bool)marquee;
- (void)SetCurrentMarquee:(bool)marquee;
- (void)SetTotalProgress:(double)current total:(double)total;
- (void)SetCurrentProgress:(double)current total:(double)total;
@end
+52
View File
@@ -0,0 +1,52 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSWindow* window = [[self view] window];
[window setLevel:kCGMainMenuWindowLevel - 1];
[window setCollectionBehavior:NSWindowCollectionBehaviorStationary |
NSWindowCollectionBehaviorCanJoinAllSpaces |
NSWindowCollectionBehaviorFullScreenAuxiliary];
}
- (void)SetDescription:(NSString*)string
{
[_labelProgress setStringValue:string];
}
- (void)SetTotalMarquee:(bool)marquee
{
[_progressTotal setIndeterminate:marquee];
}
- (void)SetCurrentMarquee:(bool)marquee
{
[_progressCurrent setIndeterminate:marquee];
}
- (void)SetTotalProgress:(double)current total:(double)total
{
[_progressTotal setMaxValue:total];
[_progressTotal setDoubleValue:current];
}
- (void)SetCurrentProgress:(double)current total:(double)total
{
[_progressCurrent setMaxValue:total];
[_progressCurrent setDoubleValue:current];
}
- (void)setRepresentedObject:(id)representedObject
{
[super setRepresentedObject:representedObject];
}
@end
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <Cocoa/Cocoa.h>
int main(int argc, const char** argv)
{
if (argc == 1)
{
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"This updater is not meant to be launched directly."];
[alert setAlertStyle:NSAlertStyleWarning];
[alert setInformativeText:@"Configure Auto-Update in Dolphin's settings instead."];
[alert runModal];
return 1;
}
return NSApplicationMain(argc, argv);
}
+76 -12
View File
@@ -19,23 +19,50 @@
#include <Windows.h>
#endif
#ifdef __APPLE__
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#if defined _WIN32 || defined __APPLE__
#define OS_SUPPORTS_UPDATER
#endif
namespace
{
#ifdef _WIN32
const char UPDATER_FILENAME[] = "Updater.exe";
const char UPDATER_RELOC_FILENAME[] = "Updater.2.exe";
#elif defined(__APPLE__)
const char UPDATER_FILENAME[] = "Dolphin Updater.app";
const char UPDATER_RELOC_FILENAME[] = ".Dolphin Updater.2.app";
#endif
const char UPDATER_LOG_FILE[] = "Updater.log";
std::wstring MakeUpdaterCommandLine(const std::map<std::string, std::string>& flags)
#ifdef OS_SUPPORTS_UPDATER
std::string MakeUpdaterCommandLine(const std::map<std::string, std::string>& flags)
{
std::wstring cmdline = UTF8ToUTF16(UPDATER_FILENAME) + L" "; // Start with a fake argv[0].
#ifdef __APPLE__
std::string cmdline = "\"" + File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME +
"/Contents/MacOS/Dolphin Updater\"";
#else
std::string cmdline = File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME;
#endif
cmdline += " ";
for (const auto& pair : flags)
{
std::string value = "--" + pair.first + "=" + pair.second;
value = ReplaceAll(value, "\"", "\\\""); // Escape double quotes.
value = "\"" + value + "\" ";
cmdline += UTF8ToUTF16(value);
cmdline += value;
}
return cmdline;
}
@@ -44,7 +71,12 @@ std::wstring MakeUpdaterCommandLine(const std::map<std::string, std::string>& fl
void CleanupFromPreviousUpdate()
{
std::string reloc_updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME;
#ifdef __APPLE__
File::DeleteDirRecursively(reloc_updater_path);
#else
File::Delete(reloc_updater_path);
#endif
}
#endif
@@ -93,28 +125,40 @@ std::string GenerateChangelog(const picojson::array& versions)
bool AutoUpdateChecker::SystemSupportsAutoUpdates()
{
#ifdef _WIN32
#if defined _WIN32 || defined __APPLE__
return true;
#else
return false;
#endif
}
static std::string GetPlatformID()
{
#if defined _WIN32
return "win";
#elif defined __APPLE__
return "macos";
#else
return "unknown";
#endif
}
void AutoUpdateChecker::CheckForUpdate()
{
// Don't bother checking if updates are not supported or not enabled.
if (!SystemSupportsAutoUpdates() || SConfig::GetInstance().m_auto_update_track.empty())
return;
#ifdef _WIN32
#ifdef OS_SUPPORTS_UPDATER
CleanupFromPreviousUpdate();
#endif
std::string version_hash = SConfig::GetInstance().m_auto_update_hash_override.empty() ?
SCM_REV_STR :
SConfig::GetInstance().m_auto_update_hash_override;
std::string url = "https://dolphin-emu.org/update/check/v0/" +
SConfig::GetInstance().m_auto_update_track + "/" + version_hash;
std::string url = "https://dolphin-emu.org/update/check/v1/" +
SConfig::GetInstance().m_auto_update_track + "/" + version_hash + "/" +
GetPlatformID();
Common::HttpRequest req{std::chrono::seconds{10}};
auto resp = req.Get(url);
@@ -157,12 +201,16 @@ void AutoUpdateChecker::CheckForUpdate()
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info,
AutoUpdateChecker::RestartMode restart_mode)
{
#ifdef _WIN32
#ifdef OS_SUPPORTS_UPDATER
std::map<std::string, std::string> updater_flags;
updater_flags["this-manifest-url"] = info.this_manifest_url;
updater_flags["next-manifest-url"] = info.next_manifest_url;
updater_flags["content-store-url"] = info.content_store_url;
#ifdef _WIN32
updater_flags["parent-pid"] = std::to_string(GetCurrentProcessId());
#else
updater_flags["parent-pid"] = std::to_string(getpid());
#endif
updater_flags["install-base-path"] = File::GetExeDirectory();
updater_flags["log-file"] = File::GetExeDirectory() + DIR_SEP + UPDATER_LOG_FILE;
@@ -172,19 +220,35 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma
// Copy the updater so it can update itself if needed.
std::string updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_FILENAME;
std::string reloc_updater_path = File::GetExeDirectory() + DIR_SEP + UPDATER_RELOC_FILENAME;
#ifdef __APPLE__
File::CopyDir(updater_path, reloc_updater_path);
chmod((reloc_updater_path + "/Contents/MacOS/Dolphin Updater").c_str(), 0700);
#else
File::Copy(updater_path, reloc_updater_path);
#endif
// Run the updater!
std::wstring command_line = MakeUpdaterCommandLine(updater_flags);
std::string command_line = MakeUpdaterCommandLine(updater_flags);
INFO_LOG(COMMON, "Updater command line: %s", command_line.c_str());
#ifdef _WIN32
STARTUPINFO sinfo = {sizeof(info)};
sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process.
PROCESS_INFORMATION pinfo;
INFO_LOG(COMMON, "Updater command line: %s", UTF16ToUTF8(command_line).c_str());
if (!CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(),
const_cast<wchar_t*>(command_line.c_str()), nullptr, nullptr, FALSE, 0,
nullptr, nullptr, &sinfo, &pinfo))
const_cast<wchar_t*>(UTF8ToUTF16(command_line).c_str()), nullptr, nullptr,
FALSE, 0, nullptr, nullptr, &sinfo, &pinfo))
{
ERROR_LOG(COMMON, "Could not start updater process: error=%d", GetLastError());
}
#else
if (popen(command_line.c_str(), "r") == nullptr)
{
ERROR_LOG(COMMON, "Could not start updater process: error=%d", errno);
}
#endif
#endif
}