diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt index e3bfa09e2..38a10bf3f 100644 --- a/tdutils/CMakeLists.txt +++ b/tdutils/CMakeLists.txt @@ -60,6 +60,7 @@ set(TDUTILS_SOURCE td/utils/port/StdStreams.cpp td/utils/port/thread_local.cpp td/utils/port/UdpSocketFd.cpp + td/utils/port/uname.cpp td/utils/port/user.cpp td/utils/port/wstring_convert.cpp @@ -139,6 +140,7 @@ set(TDUTILS_SOURCE td/utils/port/thread.h td/utils/port/thread_local.h td/utils/port/UdpSocketFd.h + td/utils/port/uname.h td/utils/port/user.h td/utils/port/wstring_convert.h diff --git a/tdutils/td/utils/port/uname.cpp b/tdutils/td/utils/port/uname.cpp new file mode 100644 index 000000000..ea9aa63fd --- /dev/null +++ b/tdutils/td/utils/port/uname.cpp @@ -0,0 +1,122 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/utils/port/uname.h" + +#include "td/utils/port/config.h" + +#include "td/utils/common.h" +#include "td/utils/logging.h" +#include "td/utils/misc.h" + +#if TD_PORT_POSIX +#if TD_ANDROID +#include +#else +#include +#endif +#endif + +namespace td { + +Slice get_operating_system_name() { + static string result = []() -> string { +#if TD_PORT_POSIX +#if TD_ANDROID + char version[PROP_VALUE_MAX + 1]; + int length = __system_property_get("ro.build.version.release", version); + return length <= 0 ? string("Android") : "Android " + string(version, length); +#else + utsname name; + int err = uname(&name); + if (err == 0) { + auto os_name = trim(PSTRING() << name.sysname << " " << name.release); + if (!os_name.empty()) { + return os_name; + } + } + LOG(ERROR) << "Failed to identify OS name; use generic one"; +#endif + +#if TD_DARWIN_IOS + return "iOS"; +#elif TD_DARWIN_TV_OS + return "tvOS"; +#elif TD_DARWIN_WATCH_OS + return "watchOS"; +#elif TD_DARWIN_MAC + return "macOS"; +#elif TD_DARWIN + return "Darwin"; +#elif TD_ANDROID + return "Android"; +#elif TD_TIZEN + return "Tizen"; +#elif TD_LINUX + return "Linux"; +#elif TD_FREEBSD + return "FreeBSD"; +#elif TD_OPENBSD + return "OpenBSD"; +#elif TD_NETBSD + return "NetBSD"; +#elif TD_CYGWIN + return "Cygwin"; +#elif TD_EMSCRIPTEN + return "Emscripten"; +#else + return "Unix"; +#endif + +#else + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) + auto handle = GetModuleHandle(L"ntdll.dll"); + if (handle != nullptr) { + using RtlGetVersionPtr = LONG(WINAPI *)(PRTL_OSVERSIONINFOEXW); + RtlGetVersionPtr RtlGetVersion = reinterpret_cast(GetProcAddress(handle, "RtlGetVersion")); + if (RtlGetVersion != nullptr) { + RTL_OSVERSIONINFOEXW os_version_info = {}; + os_version_info.dwOSVersionInfoSize = sizeof(os_version_info); + if (RtlGetVersion(&os_version_info) == 0) { + auto major = os_version_info.dwMajorVersion; + auto minor = os_version_info.dwMinorVersion; + bool is_server = os_version_info.wProductType != VER_NT_WORKSTATION; + + if (major == 10 && minor >= 0) { + if (is_server) { + return os_version_info.dwBuildNumber >= 17623 ? "Windows Server 2019" : "Windows Server 2016"; + } + return "Windows 10"; + } + if (major == 6 && minor == 3) { + return is_server ? "Windows Server 2012 R2" : "Windows 8.1"; + } + if (major == 6 && minor == 2) { + return is_server ? "Windows Server 2012" : "Windows 8"; + } + if (major == 6 && minor == 1) { + return is_server ? "Windows Server 2008 R2" : "Windows 7"; + } + if (major == 6 && minor == 0) { + return is_server ? "Windows Server 2008" : "Windows Vista"; + } + return is_server ? "Windows Server" : "Windows"; + } + } + } +#elif TD_WINRT + return "Windows 10"; +#endif + + LOG(ERROR) << "Failed to identify OS name; use generic one"; + return "Windows"; +#endif + }(); + return result; +} + +} // namespace td diff --git a/tdutils/td/utils/port/uname.h b/tdutils/td/utils/port/uname.h new file mode 100644 index 000000000..4760eb7b4 --- /dev/null +++ b/tdutils/td/utils/port/uname.h @@ -0,0 +1,15 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/utils/Slice.h" + +namespace td { + +Slice get_operating_system_name(); + +} diff --git a/tdutils/test/misc.cpp b/tdutils/test/misc.cpp index ec61a5183..178e740fa 100644 --- a/tdutils/test/misc.cpp +++ b/tdutils/test/misc.cpp @@ -24,6 +24,7 @@ #include "td/utils/port/sleep.h" #include "td/utils/port/Stat.h" #include "td/utils/port/thread.h" +#include "td/utils/port/uname.h" #include "td/utils/port/wstring_convert.h" #include "td/utils/Random.h" #include "td/utils/Slice.h" @@ -1080,6 +1081,7 @@ TEST(Misc, Hasher) { test_hash(); #endif } + TEST(Misc, CancellationToken) { CancellationTokenSource source; source.cancel(); @@ -1099,3 +1101,12 @@ TEST(Misc, CancellationToken) { source = CancellationTokenSource{}; CHECK(token4); } + +TEST(Misc, uname) { + auto first_name = get_operating_system_name(); + auto second_name = get_operating_system_name(); + ASSERT_STREQ(first_name, second_name); + ASSERT_EQ(first_name.begin(), second_name.begin()); + ASSERT_TRUE(!first_name.empty()); + LOG(ERROR) << first_name; +}