summaryrefslogtreecommitdiff
path: root/zen/sys_version.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/sys_version.cpp')
-rw-r--r--zen/sys_version.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/zen/sys_version.cpp b/zen/sys_version.cpp
new file mode 100644
index 00000000..46918315
--- /dev/null
+++ b/zen/sys_version.cpp
@@ -0,0 +1,91 @@
+// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#include "sys_version.h"
+ #include <iostream>
+ #include "file_io.h"
+ #include "shell_execute.h"
+
+using namespace zen;
+
+
+OsVersionDetail zen::getOsVersionDetail() //throw SysError
+{
+ /* prefer lsb_release: lsb_release Distributor ID: Debian
+ 1. terser OS name Release: 8.11
+ 2. detailed version number
+ /etc/os-release NAME="Debian GNU/Linux"
+ VERSION_ID="8" */
+ std::wstring osName;
+ std::wstring osVersion;
+ try
+ {
+ if (const auto [exitCode, output] = consoleExecute("lsb_release --id -s", std::nullopt); //throw SysError
+ exitCode != 0)
+ throw SysError(formatSystemError("lsb_release --id", replaceCpy(_("Exit code %x"), L"%x", numberTo<std::wstring>(exitCode)), output));
+ else
+ osName = trimCpy(output);
+
+ if (const auto [exitCode, output] = consoleExecute("lsb_release --release -s", std::nullopt); //throw SysError
+ exitCode != 0)
+ throw SysError(formatSystemError("lsb_release --release", replaceCpy(_("Exit code %x"), L"%x", numberTo<std::wstring>(exitCode)), output));
+ else
+ osVersion = trimCpy(output);
+ }
+ //lsb_release not available on some systems: https://freefilesync.org/forum/viewtopic.php?t=7191
+ catch (SysError&) // => fall back to /etc/os-release: https://www.freedesktop.org/software/systemd/man/os-release.html
+ {
+ std::string releaseInfo;
+ try
+ {
+ releaseInfo = getFileContent("/etc/os-release", nullptr /*notifyUnbufferedIO*/); //throw FileError
+ }
+ catch (const FileError& e) { throw SysError(replaceCpy(e.toString(), L"\n\n", L'\n')); } //errors should be further enriched by context info => SysError
+
+ for (const std::string& line : split(releaseInfo, '\n', SplitOnEmpty::skip))
+ if (startsWith(line, "NAME="))
+ osName = utfTo<std::wstring>(afterFirst(line, '=', IfNotFoundReturn::none));
+ else if (startsWith(line, "VERSION_ID="))
+ osVersion = utfTo<std::wstring>(afterFirst(line, '=', IfNotFoundReturn::none));
+ //PRETTY_NAME? too wordy! e.g. "Fedora 17 (Beefy Miracle)"
+
+ trim(osName, true, true, [](char c) { return c == L'"' || c == L'\''; });
+ trim(osVersion, true, true, [](char c) { return c == L'"' || c == L'\''; });
+ }
+
+ if (osName.empty())
+ throw SysError(L"Operating system release could not be determined."); //should never happen!
+ //osVersion is usually available, except for Arch Linux: https://freefilesync.org/forum/viewtopic.php?t=7276
+ // lsb_release Release is "rolling"
+ // etc/os-release: VERSION_ID is missing
+
+ std::vector<std::wstring> verDigits = split<std::wstring>(osVersion, L'.', SplitOnEmpty::allow); //e.g. "7.7.1908"
+ verDigits.resize(2);
+
+ return OsVersionDetail
+ {
+ {
+ stringTo<int>(verDigits[0]),
+ stringTo<int>(verDigits[1])
+ },
+ osVersion, osName
+ };
+}
+
+
+OsVersion zen::getOsVersion()
+{
+ try
+ {
+ static const OsVersionDetail verDetail = getOsVersionDetail(); //throw SysError
+ return verDetail.version;
+ }
+ catch (const SysError& e)
+ {
+ std::cerr << utfTo<std::string>(e.toString()) << '\n';
+ return {}; //sigh, it's a jungle out there: https://freefilesync.org/forum/viewtopic.php?t=7276
+ }
+}
bgstack15