From 926abbe189ea8af6db6898acc4ea396636852c07 Mon Sep 17 00:00:00 2001 From: ilya-fedin Date: Wed, 8 Apr 2020 06:40:45 +0400 Subject: [PATCH] Adapt autoupdater for AppImage (#21) --- .github/workflows/appimage-release.yml | 22 +- .github/workflows/appimage.yml | 5 - Telegram/Patches/AppImageKit-checkrt.diff | 320 +++++++++++++++++++ Telegram/Patches/AppRun.c.diff | 43 --- Telegram/SourceFiles/core/update_checker.cpp | 6 + 5 files changed, 340 insertions(+), 56 deletions(-) delete mode 100644 Telegram/Patches/AppRun.c.diff diff --git a/.github/workflows/appimage-release.yml b/.github/workflows/appimage-release.yml index ce2368a71..79cfe2822 100644 --- a/.github/workflows/appimage-release.yml +++ b/.github/workflows/appimage-release.yml @@ -461,6 +461,7 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DTDESKTOP_API_ID=${API_ID} \ -DTDESKTOP_API_HASH=${API_HASH} \ + -DDESKTOP_APP_DISABLE_AUTOUPDATE=OFF \ -DDESKTOP_APP_USE_PACKAGED_FONTS=OFF \ -DDESKTOP_APP_USE_PACKAGED_GSL=OFF \ -DDESKTOP_APP_USE_PACKAGED_EXPECTED=OFF \ @@ -485,11 +486,6 @@ jobs: git clone --depth=1 $GIT/darealshinji/AppImageKit-checkrt cd AppImageKit-checkrt git apply ../../$REPO_NAME/Telegram/Patches/AppImageKit-checkrt.diff - - # We don't need arguments from the desktop file - make AppRun.c - git apply ../../$REPO_NAME/Telegram/Patches/AppRun.c.diff - make -j$(nproc) - name: AppImage build. @@ -509,14 +505,24 @@ jobs: -exclude-libs=libatk-1.0.so.0,libatk-bridge-2.0.so.0,libatspi.so.0,libcairo-gobject.so.2,libcairo.so.2,libgdk-3.so.0,libgdk-x11-2.0.so.0,libgmodule-2.0.so.0,libgtk-3.so.0,libgtk-x11-2.0.so.0,libpixman-1.so.0,libpng12.so.0 \ -extra-plugins=bearer,iconengines,imageformats,platforminputcontexts,platforms/libqwayland-egl.so,platforms/libqwayland-generic.so,platformthemes/libqgtk3.so,wayland-decoration-client,wayland-graphics-integration-client,wayland-shell-integration - - name: Get artifact name. + - name: Move artifact. if: env.ONLY_CACHE == 'false' run: | cd $REPO_NAME - artifact_name=$(echo Kotatogram_Desktop*.AppImage) + tag_name=${GITHUB_REF##*/} + version=${tag_name#k} + appimage_name=$(echo Kotatogram_Desktop*.AppImage) + artifact_name=KtgAppImage.$version.tar.xz echo ::set-env name=ARTIFACT_NAME::$artifact_name + mkdir -p artifact/Kotatogram + mv $appimage_name artifact/Kotatogram/Kotatogram.AppImage + mv bin/Updater artifact/Kotatogram + + cd artifact + tar -caf $artifact_name Kotatogram + - name: Upload release asset. id: upload-release-asset if: env.ONLY_CACHE == 'false' @@ -525,6 +531,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ env.REPO_NAME }}/${{ env.ARTIFACT_NAME }} + asset_path: ./${{ env.REPO_NAME }}/artifact/${{ env.ARTIFACT_NAME }} asset_name: ${{ env.ARTIFACT_NAME }} asset_content_type: application/octet-stream diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index a46167de7..a075c9b1b 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -492,11 +492,6 @@ jobs: git clone --depth=1 $GIT/darealshinji/AppImageKit-checkrt cd AppImageKit-checkrt git apply ../../$REPO_NAME/Telegram/Patches/AppImageKit-checkrt.diff - - # We don't need arguments from the desktop file - make AppRun.c - git apply ../../$REPO_NAME/Telegram/Patches/AppRun.c.diff - make -j$(nproc) - name: AppImage build. diff --git a/Telegram/Patches/AppImageKit-checkrt.diff b/Telegram/Patches/AppImageKit-checkrt.diff index 073f89ba1..58fdcd1cb 100644 --- a/Telegram/Patches/AppImageKit-checkrt.diff +++ b/Telegram/Patches/AppImageKit-checkrt.diff @@ -1,3 +1,256 @@ +diff --git a/AppRun.c.patch b/AppRun.c.patch +index d408b38..53dfc48 100644 +--- a/AppRun.c.patch ++++ b/AppRun.c.patch +@@ -1,32 +1,225 @@ + --- a/AppRun.c + +++ b/AppRun.c +-@@ -164,6 +164,10 @@ +- char *old_env; +- size_t length; +- const char *format; +-+ checkrt(usr_in_appdir); ++@@ -32,6 +32,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #define die(...) \ ++ do { \ ++@@ -102,118 +103,120 @@ ++ line[n] = '\0'; ++ } ++ ++- // count arguments ++- char* arg = exe; ++- int argcount = 0; ++- while ((arg += (strlen(arg)+1)) && *arg) ++- argcount += 1; ++- ++- // merge args ++- char* outargptrs[argcount + argc + 1]; ++- outargptrs[0] = exe; ++- int outargindex = 1; ++- arg = exe; ++- int argc_ = argc - 1; // argv[0] is the filename ++- char** argv_ = argv + 1; ++- while ((arg += (strlen(arg)+1)) && *arg) { ++- if (arg[0] == '%' || (arg[0] == '"' && arg[1] == '%')) { // handle desktop file field codes ++- char code = arg[arg[0] == '%' ? 1 : 2]; ++- switch(code) { ++- case 'f': ++- case 'u': ++- if (argc_ > 0) { ++- outargptrs[outargindex++] = *argv_++; ++- argc_--; ++- } ++- break; ++- case 'F': ++- case 'U': ++- while (argc_ > 0) { ++- outargptrs[outargindex++] = *argv_++; ++- argc_--; ++- } ++- break; ++- case 'i': ++- case 'c': ++- case 'k': ++- fprintf(stderr, "WARNING: Desktop file field code %%%c is not currently supported\n", code); ++- break; ++- default: ++- fprintf(stderr, "WARNING: Invalid desktop file field code %%%c\n", code); ++- break; ++- } ++- } else { ++- outargptrs[outargindex++] = arg; +++ int pid; +++ if ((pid = fork()) == -1) { +++ int error = errno; +++ die("fork() failed: %s\n", strerror(error)); +++ } else if (pid == 0) { +++ // count arguments +++ char* arg = exe; +++ int argcount = 0; +++ while ((arg += (strlen(arg)+1)) && *arg) +++ argcount += 1; +++ +++ // merge args +++ char* outargptrs[argcount + argc + 1]; +++ outargptrs[0] = exe; +++ int outargindex = 1; +++ int argc_ = argc - 1; // argv[0] is the filename +++ char** argv_ = argv + 1; +++ while (argc_ > 0) { +++ outargptrs[outargindex++] = *argv_++; +++ argc_--; ++ } ++- } ++- while (argc_ > 0) { ++- outargptrs[outargindex++] = *argv_++; ++- argc_--; ++- } ++- outargptrs[outargindex] = '\0'; // trailing null argument required by execvp() +++ outargptrs[outargindex] = '\0'; // trailing null argument required by execvp() +++ +++ // change directory +++ size_t appdir_s = strlen(appdir); +++ char *usr_in_appdir = malloc(appdir_s + 5); +++ snprintf(usr_in_appdir, appdir_s + 5, "%s/usr", appdir); +++ ret = chdir(usr_in_appdir); +++ if (ret != 0) +++ die("Could not cd into %s\n", usr_in_appdir); +++ +++ // set environment variables +++ char *old_env; +++ size_t length; +++ const char *format; + + +-+ if (optional_ld_preload) +-+ putenv(optional_ld_preload); +++ checkrt(usr_in_appdir); + +- /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ +- SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); +-@@ -172,7 +176,7 @@ +- SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); ++- // change directory ++- size_t appdir_s = strlen(appdir); ++- char *usr_in_appdir = malloc(appdir_s + 5); ++- snprintf(usr_in_appdir, appdir_s + 5, "%s/usr", appdir); ++- ret = chdir(usr_in_appdir); ++- if (ret != 0) ++- die("Could not cd into %s\n", usr_in_appdir); +++ if (optional_ld_preload) +++ putenv(optional_ld_preload); + +- old_env = getenv("LD_LIBRARY_PATH") ?: ""; ++- // set environment variables ++- char *old_env; ++- size_t length; ++- const char *format; +++ /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ +++ SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); ++ ++- /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ ++- SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); +++ old_env = getenv("PATH") ?: ""; +++ SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); ++ ++- old_env = getenv("PATH") ?: ""; ++- SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); +++ old_env = getenv("LD_LIBRARY_PATH") ?: ""; +++ SET_NEW_ENV(new_ld_library_path, strlen(optional_ld_library_path) + appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", optional_ld_library_path, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); ++ ++- old_env = getenv("LD_LIBRARY_PATH") ?: ""; + - SET_NEW_ENV(new_ld_library_path, appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); +-+ SET_NEW_ENV(new_ld_library_path, strlen(optional_ld_library_path) + appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", optional_ld_library_path, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); +- +- old_env = getenv("PYTHONPATH") ?: ""; +- SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); +-@@ -201,6 +205,9 @@ +- if (ret == -1) +++ old_env = getenv("PYTHONPATH") ?: ""; +++ SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); ++ ++- old_env = getenv("PYTHONPATH") ?: ""; ++- SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); +++ old_env = getenv("XDG_DATA_DIRS") ?: "/usr/local/share/:/usr/share/"; +++ SET_NEW_ENV(new_xdg_data_dirs, appdir_s + strlen(old_env), "XDG_DATA_DIRS=%s/usr/share/:%s", appdir, old_env); ++ ++- old_env = getenv("XDG_DATA_DIRS") ?: "/usr/local/share/:/usr/share/"; ++- SET_NEW_ENV(new_xdg_data_dirs, appdir_s + strlen(old_env), "XDG_DATA_DIRS=%s/usr/share/:%s", appdir, old_env); +++ old_env = getenv("PERLLIB") ?: ""; +++ SET_NEW_ENV(new_perllib, appdir_s*2 + strlen(old_env), "PERLLIB=%s/usr/share/perl5/:%s/usr/lib/perl5/:%s", appdir, appdir, old_env); ++ ++- old_env = getenv("PERLLIB") ?: ""; ++- SET_NEW_ENV(new_perllib, appdir_s*2 + strlen(old_env), "PERLLIB=%s/usr/share/perl5/:%s/usr/lib/perl5/:%s", appdir, appdir, old_env); +++ /* http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges */ +++ old_env = getenv("GSETTINGS_SCHEMA_DIR") ?: ""; +++ SET_NEW_ENV(new_gsettings_schema_dir, appdir_s + strlen(old_env), "GSETTINGS_SCHEMA_DIR=%s/usr/share/glib-2.0/schemas/:%s", appdir, old_env); ++ ++- /* http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges */ ++- old_env = getenv("GSETTINGS_SCHEMA_DIR") ?: ""; ++- SET_NEW_ENV(new_gsettings_schema_dir, appdir_s + strlen(old_env), "GSETTINGS_SCHEMA_DIR=%s/usr/share/glib-2.0/schemas/:%s", appdir, old_env); +++ old_env = getenv("QT_PLUGIN_PATH") ?: ""; +++ SET_NEW_ENV(new_qt_plugin_path, appdir_s*10 + strlen(old_env), "QT_PLUGIN_PATH=%s/usr/lib/qt4/plugins/:%s/usr/lib/i386-linux-gnu/qt4/plugins/:%s/usr/lib/x86_64-linux-gnu/qt4/plugins/:%s/usr/lib32/qt4/plugins/:%s/usr/lib64/qt4/plugins/:%s/usr/lib/qt5/plugins/:%s/usr/lib/i386-linux-gnu/qt5/plugins/:%s/usr/lib/x86_64-linux-gnu/qt5/plugins/:%s/usr/lib32/qt5/plugins/:%s/usr/lib64/qt5/plugins/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); ++ ++- old_env = getenv("QT_PLUGIN_PATH") ?: ""; ++- SET_NEW_ENV(new_qt_plugin_path, appdir_s*10 + strlen(old_env), "QT_PLUGIN_PATH=%s/usr/lib/qt4/plugins/:%s/usr/lib/i386-linux-gnu/qt4/plugins/:%s/usr/lib/x86_64-linux-gnu/qt4/plugins/:%s/usr/lib32/qt4/plugins/:%s/usr/lib64/qt4/plugins/:%s/usr/lib/qt5/plugins/:%s/usr/lib/i386-linux-gnu/qt5/plugins/:%s/usr/lib/x86_64-linux-gnu/qt5/plugins/:%s/usr/lib32/qt5/plugins/:%s/usr/lib64/qt5/plugins/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); +++ SET_NEW_ENV(new_gspath, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH=%s/usr/lib/gstreamer:%s", appdir, old_env); +++ SET_NEW_ENV(new_gspath1, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH_1_0=%s/usr/lib/gstreamer-1.0:%s", appdir, old_env); +++ +++ /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ +++ putenv("PYTHONDONTWRITEBYTECODE=1"); ++ ++- SET_NEW_ENV(new_gspath, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH=%s/usr/lib/gstreamer:%s", appdir, old_env); ++- SET_NEW_ENV(new_gspath1, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH_1_0=%s/usr/lib/gstreamer-1.0:%s", appdir, old_env); +++ /* Set pid & ppid */ +++ pid_t pid = getpid(); +++ pid_t ppid = getppid(); ++ ++- /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ ++- putenv("PYTHONDONTWRITEBYTECODE=1"); +++ int pid_len = snprintf(NULL, 0, "%d", pid); +++ int ppid_len = snprintf(NULL, 0, "%d", ppid); +++ +++ char *s_pid = malloc(pid_len + 1); +++ snprintf(s_pid, pid_len + 1, "%d", pid); +++ +++ char *s_ppid = malloc(ppid_len + 1); +++ snprintf(s_ppid, ppid_len + 1, "%d", ppid); +++ +++ setenv("PID", s_pid, 1); +++ setenv("PPID", s_ppid, 1); ++ ++- /* Run */ ++- ret = execvp(exe, outargptrs); +++ /* Run */ +++ execvp(exe, outargptrs); ++ ++- int error = errno; +++ free(optional_ld_library_path); +++ if (optional_ld_preload) +++ free(optional_ld_preload); +++ +++ free(usr_in_appdir); +++ free(new_pythonhome); +++ free(new_path); +++ free(new_ld_library_path); +++ free(new_pythonpath); +++ free(new_xdg_data_dirs); +++ free(new_perllib); +++ free(new_gsettings_schema_dir); +++ free(new_qt_plugin_path); ++ ++- if (ret == -1) +++ int error = errno; + die("Error executing '%s': %s\n", exe, strerror(error)); +- +-+ free(optional_ld_library_path); +-+ if (optional_ld_preload) +-+ free(optional_ld_preload); +++ } +++ +++ int status = 0; +++ int rv = waitpid(pid, &status, 0); +++ status = rv > 0 && WIFEXITED (status) ? WEXITSTATUS (status) : 1; ++ + free(line); + free(desktop_file); +- free(usr_in_appdir); ++- free(usr_in_appdir); ++- free(new_pythonhome); ++- free(new_path); ++- free(new_ld_library_path); ++- free(new_pythonpath); ++- free(new_xdg_data_dirs); ++- free(new_perllib); ++- free(new_gsettings_schema_dir); ++- free(new_qt_plugin_path); ++- return 0; +++ return status; ++ } diff --git a/Makefile b/Makefile index cd8fe34..dab0cff 100644 --- a/Makefile @@ -23,3 +276,70 @@ index 7607d61..f5a187f 100644 DEBUG("%s ==> %s (%d)\n", stdcxx_sys_lib, stdcxx_sys_sym, stdcxx_sys_ver); DEBUG("%s ==> %s (%d)\n\n", stdcxx_bundle_lib, stdcxx_bundle_sym, stdcxx_bundle_ver); } +diff --git a/env.c b/env.c +index 6776bff..9c1d476 100755 +--- a/env.c ++++ b/env.c +@@ -43,6 +43,21 @@ void env_free(char* const *env) { + free((char**)env); + } + ++pid_t get_parent_pid() { ++ pid_t ppid = 0; ++ char *s_ppid = getenv("PPID"); ++ ++ if(s_ppid) { ++ ppid = atoi(s_ppid); ++ } ++ ++ if (!ppid) { ++ ppid = getppid(); ++ } ++ ++ return ppid; ++} ++ + static size_t get_number_of_variables(FILE *file, char **buffer, size_t *len) { + size_t number = 0; + +@@ -103,7 +118,7 @@ static char* const* read_env_from_process(pid_t pid) { + } + + char* const* read_parent_env() { +- pid_t ppid = getppid(); ++ pid_t ppid = get_parent_pid(); + return read_env_from_process(ppid); + } + +diff --git a/env.h b/env.h +index affc2d4..36f491c 100755 +--- a/env.h ++++ b/env.h +@@ -3,6 +3,7 @@ + + #include + ++pid_t get_parent_pid(); + char* const* read_parent_env(); + void env_free(char* const *env); + +diff --git a/exec.c b/exec.c +index ad0f489..29d04ec 100644 +--- a/exec.c ++++ b/exec.c +@@ -79,12 +79,12 @@ static int exec_common(execve_func_t function, const char *filename, char* const + DEBUG("filename %s, fullpath %s\n", filename, fullpath); + char* const *env = envp; + if (is_external_process(fullpath)) { +- DEBUG("External process detected. Restoring env vars from parent %d\n", getppid()); ++ DEBUG("External process detected. Restoring env vars from parent %d\n", get_parent_pid()); + env = read_parent_env(); +- if (!env) ++ if (!env) { + env = envp; +- else + DEBUG("Error restoring env vars from parent\n"); ++ } + } + int ret = function(filename, argv, env); + diff --git a/Telegram/Patches/AppRun.c.diff b/Telegram/Patches/AppRun.c.diff deleted file mode 100644 index 5f5a5f807..000000000 --- a/Telegram/Patches/AppRun.c.diff +++ /dev/null @@ -1,43 +0,0 @@ ---- a/AppRun.c -+++ b/AppRun.c -@@ -112,40 +112,8 @@ - char* outargptrs[argcount + argc + 1]; - outargptrs[0] = exe; - int outargindex = 1; -- arg = exe; - int argc_ = argc - 1; // argv[0] is the filename - char** argv_ = argv + 1; -- while ((arg += (strlen(arg)+1)) && *arg) { -- if (arg[0] == '%' || (arg[0] == '"' && arg[1] == '%')) { // handle desktop file field codes -- char code = arg[arg[0] == '%' ? 1 : 2]; -- switch(code) { -- case 'f': -- case 'u': -- if (argc_ > 0) { -- outargptrs[outargindex++] = *argv_++; -- argc_--; -- } -- break; -- case 'F': -- case 'U': -- while (argc_ > 0) { -- outargptrs[outargindex++] = *argv_++; -- argc_--; -- } -- break; -- case 'i': -- case 'c': -- case 'k': -- fprintf(stderr, "WARNING: Desktop file field code %%%c is not currently supported\n", code); -- break; -- default: -- fprintf(stderr, "WARNING: Invalid desktop file field code %%%c\n", code); -- break; -- } -- } else { -- outargptrs[outargindex++] = arg; -- } -- } - while (argc_ > 0) { - outargptrs[outargindex++] = *argv_++; - argc_--; diff --git a/Telegram/SourceFiles/core/update_checker.cpp b/Telegram/SourceFiles/core/update_checker.cpp index 3a34bfba2..83ea27f48 100644 --- a/Telegram/SourceFiles/core/update_checker.cpp +++ b/Telegram/SourceFiles/core/update_checker.cpp @@ -501,7 +501,13 @@ bool ParseCommonMap( return false; } const auto platforms = document.object(); +#ifdef Q_OS_LINUX + const auto platform = Platform::InAppImage() + ? "appimage" + : Platform::AutoUpdateKey(); +#else // Q_OS_LINUX const auto platform = Platform::AutoUpdateKey(); +#endif // !Q_OS_LINUX const auto it = platforms.constFind(platform); if (it == platforms.constEnd()) { LOG(("Update Error: MTP platform '%1' not found in response."