1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
// *****************************************************************************
// * 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()
{
static const OsVersionDetail verDetail = []
{
try
{
return getOsVersionDetail(); //throw SysError
}
catch (const SysError& e)
{
std::cerr << utfTo<std::string>(e.toString()) << '\n';
return OsVersionDetail{}; //sigh, it's a jungle out there: https://freefilesync.org/forum/viewtopic.php?t=7276
}
}();
return verDetail.version;
}
|