diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2022-09-19 15:37:14 +0200 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2022-09-22 13:48:15 +0200 |
commit | 767beb7fff6f08f5574a193967f8f814970ac289 (patch) | |
tree | 06a3378b4163481ab21f534430954653ffe59581 /src/corelib/global/qglobal.cpp | |
parent | 27197d1a123e721730cee28ea25e726aeb5768f5 (diff) |
Move the implementation and docs of QSysInfo to qsysinfo.cpp
Task-number: QTBUG-106154
Change-Id: Ib2d812104b3514fb255d79ab6e4097ec6a851e21
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 1046 |
1 files changed, 0 insertions, 1046 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 1228c98863..4b53b7e9f7 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -8,12 +8,6 @@ #include "qlist.h" #include "qdir.h" #include "qdatetime.h" -#include "qoperatingsystemversion.h" -#include "qoperatingsystemversion_p.h" -#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) -# include "qoperatingsystemversion_win_p.h" -# include "private/qwinregistry_p.h" -#endif // Q_OS_WIN || Q_OS_CYGWIN #include <private/qlocale_tools_p.h> #include "qnativeinterface.h" #include "qnativeinterface_p.h" @@ -35,28 +29,6 @@ # include <envLib.h> #endif -#ifdef Q_OS_ANDROID -#include <qjniobject.h> -#endif - -#if defined(Q_OS_SOLARIS) -# include <sys/systeminfo.h> -#endif - -#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>) -# include <IOKit/IOKitLib.h> -# include <private/qcore_mac_p.h> -#endif - -#ifdef Q_OS_UNIX -#include <sys/utsname.h> -#include <private/qcore_unix_p.h> -#endif - -#ifdef Q_OS_BSD4 -#include <sys/sysctl.h> -#endif - #if defined(Q_OS_INTEGRITY) extern "C" { // Function mmap resides in libshm_client.a. To be able to link with it one needs @@ -70,8 +42,6 @@ extern "C" { } #endif -#include "archdetect.cpp" - #ifdef qFatal // the qFatal in this file are just redirections from elsewhere, so // don't capture any context again @@ -208,44 +178,6 @@ using namespace Qt::StringLiterals; *****************************************************************************/ /*! - \class QSysInfo - \inmodule QtCore - \brief The QSysInfo class provides information about the system. - - \list - \li \l WordSize specifies the size of a pointer for the platform - on which the application is compiled. - \li \l ByteOrder specifies whether the platform is big-endian or - little-endian. - \endlist - - Some constants are defined only on certain platforms. You can use - the preprocessor symbols Q_OS_WIN and Q_OS_MACOS to test that - the application is compiled under Windows or \macos. - - \sa QLibraryInfo -*/ - -/*! - \enum QSysInfo::Sizes - - This enum provides platform-specific information about the sizes of data - structures used by the underlying architecture. - - \value WordSize The size in bits of a pointer for the platform on which - the application is compiled (32 or 64). -*/ - -/*! - \enum QSysInfo::Endian - - \value BigEndian Big-endian byte order (also called Network byte order) - \value LittleEndian Little-endian byte order - \value ByteOrder Equals BigEndian or LittleEndian, depending on - the platform's byte order. -*/ - -/*! \macro Q_OS_DARWIN \relates <QtGlobal> @@ -945,984 +877,6 @@ using namespace Qt::StringLiterals; \sa QT_DISABLE_DEPRECATED_BEFORE */ -#if defined(Q_OS_MAC) - -QT_BEGIN_INCLUDE_NAMESPACE -#include "private/qcore_mac_p.h" -#include "qnamespace.h" -QT_END_INCLUDE_NAMESPACE - -#ifdef Q_OS_DARWIN -static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) -{ -#ifdef Q_OS_MACOS - if (version.majorVersion() == 12) - return "Monterey"; - // Compare against predefined constant to handle 10.16/11.0 - if (QOperatingSystemVersion::MacOSBigSur.version().isPrefixOf(version.version())) - return "Big Sur"; - if (version.majorVersion() == 10) { - switch (version.minorVersion()) { - case 9: - return "Mavericks"; - case 10: - return "Yosemite"; - case 11: - return "El Capitan"; - case 12: - return "Sierra"; - case 13: - return "High Sierra"; - case 14: - return "Mojave"; - case 15: - return "Catalina"; - } - } - // unknown, future version -#else - Q_UNUSED(version); -#endif - return nullptr; -} -#endif - -#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qt_windows.h" -QT_END_INCLUDE_NAMESPACE - -# ifndef QT_BOOTSTRAPPED -class QWindowsSockInit -{ -public: - QWindowsSockInit(); - ~QWindowsSockInit(); - int version; -}; - -QWindowsSockInit::QWindowsSockInit() -: version(0) -{ - //### should we try for 2.2 on all platforms ?? - WSAData wsadata; - - // IPv6 requires Winsock v2.0 or better. - if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) { - qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed."); - } else { - version = 0x20; - } -} - -QWindowsSockInit::~QWindowsSockInit() -{ - WSACleanup(); -} -Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit) -# endif // QT_BOOTSTRAPPED - -static QString readVersionRegistryString(const wchar_t *subKey) -{ - return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)") - .stringValue(subKey); -} - -static inline QString windowsDisplayVersion() -{ - // https://tickets.puppetlabs.com/browse/FACT-3058 - // The "ReleaseId" key stopped updating since Windows 10 20H2. - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10_20H2) - return readVersionRegistryString(L"DisplayVersion"); - else - return readVersionRegistryString(L"ReleaseId"); -} - -static QString winSp_helper() -{ - const auto osv = qWindowsVersionInfo(); - const qint16 major = osv.wServicePackMajor; - if (major) { - QString sp = QStringLiteral("SP ") + QString::number(major); - const qint16 minor = osv.wServicePackMinor; - if (minor) - sp += u'.' + QString::number(minor); - - return sp; - } - return QString(); -} - -static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) -{ - Q_UNUSED(version); - const OSVERSIONINFOEX osver = qWindowsVersionInfo(); - const bool workstation = osver.wProductType == VER_NT_WORKSTATION; - -#define Q_WINVER(major, minor) (major << 8 | minor) - switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) { - case Q_WINVER(10, 0): - if (workstation) { - if (osver.dwBuildNumber >= 22000) - return "11"; - return "10"; - } - // else: Server - if (osver.dwBuildNumber >= 20348) - return "Server 2022"; - if (osver.dwBuildNumber >= 17763) - return "Server 2019"; - return "Server 2016"; - } -#undef Q_WINVER - // unknown, future version - return nullptr; -} - -#endif -#if defined(Q_OS_UNIX) -# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) -# define USE_ETC_OS_RELEASE -struct QUnixOSVersion -{ - // from /etc/os-release older /etc/lsb-release // redhat /etc/redhat-release // debian /etc/debian_version - QString productType; // $ID $DISTRIB_ID // single line file containing: // Debian - QString productVersion; // $VERSION_ID $DISTRIB_RELEASE // <Vendor_ID release Version_ID> // single line file <Release_ID/sid> - QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION -}; - -static QString unquote(const char *begin, const char *end) -{ - // man os-release says: - // Variable assignment values must be enclosed in double - // or single quotes if they include spaces, semicolons or - // other special characters outside of A–Z, a–z, 0–9. Shell - // special characters ("$", quotes, backslash, backtick) - // must be escaped with backslashes, following shell style. - // All strings should be in UTF-8 format, and non-printable - // characters should not be used. It is not supported to - // concatenate multiple individually quoted strings. - if (*begin == '"') { - Q_ASSERT(end[-1] == '"'); - return QString::fromUtf8(begin + 1, end - begin - 2); - } - return QString::fromUtf8(begin, end - begin); -} -static QByteArray getEtcFileContent(const char *filename) -{ - // we're avoiding QFile here - int fd = qt_safe_open(filename, O_RDONLY); - if (fd == -1) - return QByteArray(); - - QT_STATBUF sbuf; - if (QT_FSTAT(fd, &sbuf) == -1) { - qt_safe_close(fd); - return QByteArray(); - } - - QByteArray buffer(sbuf.st_size, Qt::Uninitialized); - buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size)); - qt_safe_close(fd); - return buffer; -} - -static bool readEtcFile(QUnixOSVersion &v, const char *filename, - const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey) -{ - - QByteArray buffer = getEtcFileContent(filename); - if (buffer.isEmpty()) - return false; - - const char *ptr = buffer.constData(); - const char *end = buffer.constEnd(); - const char *eol; - QByteArray line; - for (; ptr != end; ptr = eol + 1) { - // find the end of the line after ptr - eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr)); - if (!eol) - eol = end - 1; - line.setRawData(ptr, eol - ptr); - - if (line.startsWith(idKey)) { - ptr += idKey.length(); - v.productType = unquote(ptr, eol); - continue; - } - - if (line.startsWith(prettyNameKey)) { - ptr += prettyNameKey.length(); - v.prettyName = unquote(ptr, eol); - continue; - } - - if (line.startsWith(versionKey)) { - ptr += versionKey.length(); - v.productVersion = unquote(ptr, eol); - continue; - } - } - - return true; -} - -static bool readOsRelease(QUnixOSVersion &v) -{ - QByteArray id = QByteArrayLiteral("ID="); - QByteArray versionId = QByteArrayLiteral("VERSION_ID="); - QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME="); - - // man os-release(5) says: - // The file /etc/os-release takes precedence over /usr/lib/os-release. - // Applications should check for the former, and exclusively use its data - // if it exists, and only fall back to /usr/lib/os-release if it is - // missing. - return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) || - readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName); -} - -static bool readEtcLsbRelease(QUnixOSVersion &v) -{ - bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="), - QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION=")); - if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) { - // some distributions have redundant information for the pretty name, - // so try /etc/<lowercasename>-release - - // we're still avoiding QFile here - QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release"; - int fd = qt_safe_open(distrorelease, O_RDONLY); - if (fd != -1) { - QT_STATBUF sbuf; - if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.length()) { - // file apparently contains interesting information - QByteArray buffer(sbuf.st_size, Qt::Uninitialized); - buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size)); - v.prettyName = QString::fromLatin1(buffer.trimmed()); - } - qt_safe_close(fd); - } - } - - // some distributions have a /etc/lsb-release file that does not provide the values - // we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION. - // Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values, - // returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing. - return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty()); -} - -#if defined(Q_OS_LINUX) -static QByteArray getEtcFileFirstLine(const char *fileName) -{ - QByteArray buffer = getEtcFileContent(fileName); - if (buffer.isEmpty()) - return QByteArray(); - - const char *ptr = buffer.constData(); - int eol = buffer.indexOf("\n"); - return QByteArray(ptr, eol).trimmed(); -} - -static bool readEtcRedHatRelease(QUnixOSVersion &v) -{ - // /etc/redhat-release analysed should be a one line file - // the format of its content is <Vendor_ID release Version> - // i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)" - QByteArray line = getEtcFileFirstLine("/etc/redhat-release"); - if (line.isEmpty()) - return false; - - v.prettyName = QString::fromLatin1(line); - - const char keyword[] = "release "; - int releaseIndex = line.indexOf(keyword); - v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(u' '); - int spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword)); - v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword), - spaceIndex > -1 ? spaceIndex - releaseIndex - int(strlen(keyword)) : -1)); - return true; -} - -static bool readEtcDebianVersion(QUnixOSVersion &v) -{ - // /etc/debian_version analysed should be a one line file - // the format of its content is <Release_ID/sid> - // i.e. "jessie/sid" - QByteArray line = getEtcFileFirstLine("/etc/debian_version"); - if (line.isEmpty()) - return false; - - v.productType = QStringLiteral("Debian"); - v.productVersion = QString::fromLatin1(line); - return true; -} -#endif - -static bool findUnixOsVersion(QUnixOSVersion &v) -{ - if (readOsRelease(v)) - return true; - if (readEtcLsbRelease(v)) - return true; -#if defined(Q_OS_LINUX) - if (readEtcRedHatRelease(v)) - return true; - if (readEtcDebianVersion(v)) - return true; -#endif - return false; -} -# endif // USE_ETC_OS_RELEASE -#endif // Q_OS_UNIX - -#ifdef Q_OS_ANDROID -static const char *osVer_helper(QOperatingSystemVersion) -{ -/* Data: - - - -Cupcake -Donut -Eclair -Eclair -Eclair -Froyo -Gingerbread -Gingerbread -Honeycomb -Honeycomb -Honeycomb -Ice Cream Sandwich -Ice Cream Sandwich -Jelly Bean -Jelly Bean -Jelly Bean -KitKat -KitKat -Lollipop -Lollipop -Marshmallow -Nougat -Nougat -Oreo -*/ - static const char versions_string[] = - "\0" - "Cupcake\0" - "Donut\0" - "Eclair\0" - "Froyo\0" - "Gingerbread\0" - "Honeycomb\0" - "Ice Cream Sandwich\0" - "Jelly Bean\0" - "KitKat\0" - "Lollipop\0" - "Marshmallow\0" - "Nougat\0" - "Oreo\0" - "\0"; - - static const int versions_indices[] = { - 0, 0, 0, 1, 9, 15, 15, 15, - 22, 28, 28, 40, 40, 40, 50, 50, - 69, 69, 69, 80, 80, 87, 87, 96, - 108, 108, 115, -1 - }; - - static const int versions_count = (sizeof versions_indices) / (sizeof versions_indices[0]); - - // https://source.android.com/source/build-numbers.html - // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels - const int sdk_int = QJniObject::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT"); - return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]]; -} -#endif - -/*! - \since 5.4 - - Returns the architecture of the CPU that Qt was compiled for, in text - format. Note that this may not match the actual CPU that the application is - running on if there's an emulation layer or if the CPU supports multiple - architectures (like x86-64 processors supporting i386 applications). To - detect that, use currentCpuArchitecture(). - - Values returned by this function are stable and will not change over time, - so applications can rely on the returned value as an identifier, except - that new CPU types may be added over time. - - Typical returned values are (note: list not exhaustive): - \list - \li "arm" - \li "arm64" - \li "i386" - \li "ia64" - \li "mips" - \li "mips64" - \li "power" - \li "power64" - \li "sparc" - \li "sparcv9" - \li "x86_64" - \endlist - - \sa QSysInfo::buildAbi(), QSysInfo::currentCpuArchitecture() -*/ -QString QSysInfo::buildCpuArchitecture() -{ - return QStringLiteral(ARCH_PROCESSOR); -} - -/*! - \since 5.4 - - Returns the architecture of the CPU that the application is running on, in - text format. Note that this function depends on what the OS will report and - may not detect the actual CPU architecture if the OS hides that information - or is unable to provide it. For example, a 32-bit OS running on a 64-bit - CPU is usually unable to determine the CPU is actually capable of running - 64-bit programs. - - Values returned by this function are mostly stable: an attempt will be made - to ensure that they stay constant over time and match the values returned - by QSysInfo::builldCpuArchitecture(). However, due to the nature of the - operating system functions being used, there may be discrepancies. - - Typical returned values are (note: list not exhaustive): - \list - \li "arm" - \li "arm64" - \li "i386" - \li "ia64" - \li "mips" - \li "mips64" - \li "power" - \li "power64" - \li "sparc" - \li "sparcv9" - \li "x86_64" - \endlist - - \sa QSysInfo::buildAbi(), QSysInfo::buildCpuArchitecture() -*/ -QString QSysInfo::currentCpuArchitecture() -{ -#if defined(Q_OS_WIN) - // We don't need to catch all the CPU architectures in this function; - // only those where the host CPU might be different than the build target - // (usually, 64-bit platforms). - SYSTEM_INFO info; - GetNativeSystemInfo(&info); - switch (info.wProcessorArchitecture) { -# ifdef PROCESSOR_ARCHITECTURE_AMD64 - case PROCESSOR_ARCHITECTURE_AMD64: - return QStringLiteral("x86_64"); -# endif -# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 - case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: -# endif - case PROCESSOR_ARCHITECTURE_IA64: - return QStringLiteral("ia64"); - } -#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS) - // iOS-based OSes do not return the architecture on uname(2)'s result. - return buildCpuArchitecture(); -#elif defined(Q_OS_UNIX) - long ret = -1; - struct utsname u; - -# if defined(Q_OS_SOLARIS) - // We need a special call for Solaris because uname(2) on x86 returns "i86pc" for - // both 32- and 64-bit CPUs. Reference: - // http://docs.oracle.com/cd/E18752_01/html/816-5167/sysinfo-2.html#REFMAN2sysinfo-2 - // http://fxr.watson.org/fxr/source/common/syscall/systeminfo.c?v=OPENSOLARIS - // http://fxr.watson.org/fxr/source/common/conf/param.c?v=OPENSOLARIS;im=10#L530 - if (ret == -1) - ret = sysinfo(SI_ARCHITECTURE_64, u.machine, sizeof u.machine); -# endif - - if (ret == -1) - ret = uname(&u); - - // we could use detectUnixVersion() above, but we only need a field no other function does - if (ret != -1) { - // the use of QT_BUILD_INTERNAL here is simply to ensure all branches build - // as we don't often build on some of the less common platforms -# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL) - if (strcmp(u.machine, "aarch64") == 0) - return QStringLiteral("arm64"); - if (strncmp(u.machine, "armv", 4) == 0) - return QStringLiteral("arm"); -# endif -# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL) - // harmonize "powerpc" and "ppc" to "power" - if (strncmp(u.machine, "ppc", 3) == 0) - return "power"_L1 + QLatin1StringView(u.machine + 3); - if (strncmp(u.machine, "powerpc", 7) == 0) - return "power"_L1 + QLatin1StringView(u.machine + 7); - if (strcmp(u.machine, "Power Macintosh") == 0) - return "power"_L1; -# endif -# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL) - // Solaris sysinfo(2) (above) uses "sparcv9", but uname -m says "sun4u"; - // Linux says "sparc64" - if (strcmp(u.machine, "sun4u") == 0 || strcmp(u.machine, "sparc64") == 0) - return QStringLiteral("sparcv9"); - if (strcmp(u.machine, "sparc32") == 0) - return QStringLiteral("sparc"); -# endif -# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL) - // harmonize all "i?86" to "i386" - if (strlen(u.machine) == 4 && u.machine[0] == 'i' - && u.machine[2] == '8' && u.machine[3] == '6') - return QStringLiteral("i386"); - if (strcmp(u.machine, "amd64") == 0) // Solaris - return QStringLiteral("x86_64"); -# endif - return QString::fromLatin1(u.machine); - } -#endif - return buildCpuArchitecture(); -} - -/*! - \since 5.4 - - Returns the full architecture string that Qt was compiled for. This string - is useful for identifying different, incompatible builds. For example, it - can be used as an identifier to request an upgrade package from a server. - - The values returned from this function are kept stable as follows: the - mandatory components of the result will not change in future versions of - Qt, but optional suffixes may be added. - - The returned value is composed of three or more parts, separated by dashes - ("-"). They are: - - \table - \header \li Component \li Value - \row \li CPU Architecture \li The same as QSysInfo::buildCpuArchitecture(), such as "arm", "i386", "mips" or "x86_64" - \row \li Endianness \li "little_endian" or "big_endian" - \row \li Word size \li Whether it's a 32- or 64-bit application. Possible values are: - "llp64" (Windows 64-bit), "lp64" (Unix 64-bit), "ilp32" (32-bit) - \row \li (Optional) ABI \li Zero or more components identifying different ABIs possible in this architecture. - Currently, Qt has optional ABI components for ARM and MIPS processors: one - component is the main ABI (such as "eabi", "o32", "n32", "o64"); another is - whether the calling convention is using hardware floating point registers ("hardfloat" - is present). - - Additionally, if Qt was configured with \c{-qreal float}, the ABI option tag "qreal_float" - will be present. If Qt was configured with another type as qreal, that type is present after - "qreal_", with all characters other than letters and digits escaped by an underscore, followed - by two hex digits. For example, \c{-qreal long double} becomes "qreal_long_20double". - \endtable - - \sa QSysInfo::buildCpuArchitecture() -*/ -QString QSysInfo::buildAbi() -{ - // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks - // QStringLiteral on MSVC. Since the concatenation behavior we want is specified - // the same C++11 paper as the Unicode strings, we'll use that macro and hope - // that Microsoft implements the new behavior when they add support for Unicode strings. - return QStringLiteral(ARCH_FULL); -} - -static QString unknownText() -{ - return QStringLiteral("unknown"); -} - -/*! - \since 5.4 - - Returns the type of the operating system kernel Qt was compiled for. It's - also the kernel the application is running on, unless the host operating - system is running a form of compatibility or virtualization layer. - - Values returned by this function are stable and will not change over time, - so applications can rely on the returned value as an identifier, except - that new OS kernel types may be added over time. - - On Windows, this function returns the type of Windows kernel, like "winnt". - On Unix systems, it returns the same as the output of \c{uname - -s} (lowercased). - - \note This function may return surprising values: it returns "linux" - for all operating systems running Linux (including Android), "qnx" for all - operating systems running QNX, "freebsd" for - Debian/kFreeBSD, and "darwin" for \macos and iOS. For information on the type - of product the application is running on, see productType(). - - \sa QFileSelector, kernelVersion(), productType(), productVersion(), prettyProductName() -*/ -QString QSysInfo::kernelType() -{ -#if defined(Q_OS_WIN) - return QStringLiteral("winnt"); -#elif defined(Q_OS_UNIX) - struct utsname u; - if (uname(&u) == 0) - return QString::fromLatin1(u.sysname).toLower(); -#endif - return unknownText(); -} - -/*! - \since 5.4 - - Returns the release version of the operating system kernel. On Windows, it - returns the version of the NT kernel. On Unix systems, including - Android and \macos, it returns the same as the \c{uname -r} - command would return. - - If the version could not be determined, this function may return an empty - string. - - \sa kernelType(), productType(), productVersion(), prettyProductName() -*/ -QString QSysInfo::kernelVersion() -{ -#ifdef Q_OS_WIN - const auto osver = QOperatingSystemVersion::current(); - return QString::asprintf("%d.%d.%d", - osver.majorVersion(), osver.minorVersion(), osver.microVersion()); -#else - struct utsname u; - if (uname(&u) == 0) - return QString::fromLatin1(u.release); - return QString(); -#endif -} - - -/*! - \since 5.4 - - Returns the product name of the operating system this application is - running in. If the application is running on some sort of emulation or - virtualization layer (such as WINE on a Unix system), this function will - inspect the emulation / virtualization layer. - - Values returned by this function are stable and will not change over time, - so applications can rely on the returned value as an identifier, except - that new OS types may be added over time. - - \b{Linux and Android note}: this function returns "android" for Linux - systems running Android userspace, notably when using the Bionic library. - For all other Linux systems, regardless of C library being used, it tries - to determine the distribution name and returns that. If determining the - distribution name failed, it returns "unknown". - - \b{\macos note}: this function returns "macos" for all \macos systems, - regardless of Apple naming convention. Previously, in Qt 5, it returned - "osx", again regardless of Apple naming conventions. - - \b{Darwin, iOS, tvOS, and watchOS note}: this function returns "ios" for - iOS systems, "tvos" for tvOS systems, "watchos" for watchOS systems, and - "darwin" in case the system could not be determined. - - \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and - "unknown" otherwise. - - \b{Windows note}: this function return "windows" - - For other Unix-type systems, this function usually returns "unknown". - - \sa QFileSelector, kernelType(), kernelVersion(), productVersion(), prettyProductName() -*/ -QString QSysInfo::productType() -{ - // similar, but not identical to QFileSelectorPrivate::platformSelectors -#if defined(Q_OS_WIN) - return QStringLiteral("windows"); - -#elif defined(Q_OS_QNX) - return QStringLiteral("qnx"); - -#elif defined(Q_OS_ANDROID) - return QStringLiteral("android"); - -#elif defined(Q_OS_IOS) - return QStringLiteral("ios"); -#elif defined(Q_OS_TVOS) - return QStringLiteral("tvos"); -#elif defined(Q_OS_WATCHOS) - return QStringLiteral("watchos"); -#elif defined(Q_OS_MACOS) - return QStringLiteral("macos"); -#elif defined(Q_OS_DARWIN) - return QStringLiteral("darwin"); - -#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX - QUnixOSVersion unixOsVersion; - findUnixOsVersion(unixOsVersion); - if (!unixOsVersion.productType.isEmpty()) - return unixOsVersion.productType; -#endif - return unknownText(); -} - -/*! - \since 5.4 - - Returns the product version of the operating system in string form. If the - version could not be determined, this function returns "unknown". - - It will return the Android, iOS, \macos, Windows full-product - versions on those systems. - - Typical returned values are (note: list not exhaustive): - \list - \li "12" (Android 12) - \li "36" (Fedora 36) - \li "15.5" (iOS 15.5) - \li "12.4" (macOS Monterey) - \li "22.04" (Ubuntu 22.04) - \li "8.6" (watchOS 8.6) - \li "11" (Windows 11) - \li "Server 2022" (Windows Server 2022) - \endlist - - On Linux systems, it will try to determine the distribution version and will - return that. This is also done on Debian/kFreeBSD, so this function will - return Debian version in that case. - - In all other Unix-type systems, this function always returns "unknown". - - \note The version string returned from this function is not guaranteed to - be orderable. On Linux, the version of - the distribution may jump unexpectedly, please refer to the distribution's - documentation for versioning practices. - - \sa kernelType(), kernelVersion(), productType(), prettyProductName() -*/ -QString QSysInfo::productVersion() -{ -#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) - const auto version = QOperatingSystemVersion::current(); - return QString::asprintf("%d.%d", version.majorVersion(), version.minorVersion()); -#elif defined(Q_OS_WIN) - const char *version = osVer_helper(); - if (version) { - const QLatin1Char spaceChar(' '); - return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower(); - } - // fall through - -#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX - QUnixOSVersion unixOsVersion; - findUnixOsVersion(unixOsVersion); - if (!unixOsVersion.productVersion.isEmpty()) - return unixOsVersion.productVersion; -#endif - - // fallback - return unknownText(); -} - -/*! - \since 5.4 - - Returns a prettier form of productType() and productVersion(), containing - other tokens like the operating system type, codenames and other - information. The result of this function is suitable for displaying to the - user, but not for long-term storage, as the string may change with updates - to Qt. - - If productType() is "unknown", this function will instead use the - kernelType() and kernelVersion() functions. - - \sa kernelType(), kernelVersion(), productType(), productVersion() -*/ -QString QSysInfo::prettyProductName() -{ -#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) - const auto version = QOperatingSystemVersion::current(); - const int majorVersion = version.majorVersion(); - const QString versionString = QString::asprintf("%d.%d", majorVersion, version.minorVersion()); - QString result = version.name() + u' '; - const char *name = osVer_helper(version); - if (!name) - return result + versionString; - result += QLatin1StringView(name); -# if !defined(Q_OS_WIN) - return result + " ("_L1 + versionString + u')'; -# else - // (resembling winver.exe): Windows 10 "Windows 10 Version 1809" - const auto displayVersion = windowsDisplayVersion(); - if (!displayVersion.isEmpty()) - result += " Version "_L1 + displayVersion; - return result; -# endif // Windows -#elif defined(Q_OS_HAIKU) - return "Haiku "_L1 + productVersion(); -#elif defined(Q_OS_UNIX) -# ifdef USE_ETC_OS_RELEASE - QUnixOSVersion unixOsVersion; - findUnixOsVersion(unixOsVersion); - if (!unixOsVersion.prettyName.isEmpty()) - return unixOsVersion.prettyName; -# endif - struct utsname u; - if (uname(&u) == 0) - return QString::fromLatin1(u.sysname) + u' ' + QString::fromLatin1(u.release); -#endif - return unknownText(); -} - -#ifndef QT_BOOTSTRAPPED -/*! - \since 5.6 - - Returns this machine's host name, if one is configured. Note that hostnames - are not guaranteed to be globally unique, especially if they were - configured automatically. - - This function does not guarantee the returned host name is a Fully - Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the - returned name to an FQDN. - - This function returns the same as QHostInfo::localHostName(). - - \sa QHostInfo::localDomainName, machineUniqueId() -*/ -QString QSysInfo::machineHostName() -{ - // the hostname can change, so we can't cache it -#if defined(Q_OS_LINUX) - // gethostname(3) on Linux just calls uname(2), so do it ourselves - // and avoid a memcpy - struct utsname u; - if (uname(&u) == 0) - return QString::fromLocal8Bit(u.nodename); - return QString(); -#else -# ifdef Q_OS_WIN - // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll - winsockInit(); -# endif - - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); -#endif -} -#endif // QT_BOOTSTRAPPED - -enum { - UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1 -}; - -/*! - \since 5.11 - - Returns a unique ID for this machine, if one can be determined. If no - unique ID could be determined, this function returns an empty byte array. - Unlike machineHostName(), the value returned by this function is likely - globally unique. - - A unique ID is useful in network operations to identify this machine for an - extended period of time, when the IP address could change or if this - machine could have more than one IP address. For example, the ID could be - used when communicating with a server or when storing device-specific data - in shared network storage. - - Note that on some systems, this value will persist across reboots and on - some it will not. Applications should not blindly depend on this fact - without verifying the OS capabilities. In particular, on Linux systems, - this ID is usually permanent and it matches the D-Bus machine ID, except - for nodes without their own storage (replicated nodes). - - \sa machineHostName(), bootUniqueId() -*/ -QByteArray QSysInfo::machineUniqueId() -{ -#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>) - char uuid[UuidStringLen + 1]; - static const mach_port_t defaultPort = 0; // Effectively kIOMasterPortDefault/kIOMainPortDefault - io_service_t service = IOServiceGetMatchingService(defaultPort, IOServiceMatching("IOPlatformExpertDevice")); - QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0); - CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman); - return QByteArray(uuid); -#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID) - char uuid[UuidStringLen + 1]; - size_t uuidlen = sizeof(uuid); - int name[] = { CTL_KERN, KERN_HOSTUUID }; - if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0 - && uuidlen == sizeof(uuid)) - return QByteArray(uuid, uuidlen - 1); -#elif defined(Q_OS_UNIX) - // The modern name on Linux is /etc/machine-id, but that path is - // unlikely to exist on non-Linux (non-systemd) systems. The old - // path is more than enough. - static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id"; - const char *firstfilename = fullfilename + sizeof("/usr/local") - 1; - int fd = qt_safe_open(firstfilename, O_RDONLY); - if (fd == -1 && errno == ENOENT) - fd = qt_safe_open(fullfilename, O_RDONLY); - - if (fd != -1) { - char buffer[32]; // 128 bits, hex-encoded - qint64 len = qt_safe_read(fd, buffer, sizeof(buffer)); - qt_safe_close(fd); - - if (len != -1) - return QByteArray(buffer, len); - } -#elif defined(Q_OS_WIN) - // Let's poke at the registry - const QString machineGuid = QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Cryptography)") - .stringValue(u"MachineGuid"_s); - if (!machineGuid.isEmpty()) - return machineGuid.toLatin1(); -#endif - return QByteArray(); -} - -/*! - \since 5.11 - - Returns a unique ID for this machine's boot, if one can be determined. If - no unique ID could be determined, this function returns an empty byte - array. This value is expected to change after every boot and can be - considered globally unique. - - This function is currently only implemented for Linux and Apple operating - systems. - - \sa machineUniqueId() -*/ -QByteArray QSysInfo::bootUniqueId() -{ -#ifdef Q_OS_LINUX - // use low-level API here for simplicity - int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY); - if (fd != -1) { - char uuid[UuidStringLen]; - qint64 len = qt_safe_read(fd, uuid, sizeof(uuid)); - qt_safe_close(fd); - if (len == UuidStringLen) - return QByteArray(uuid, UuidStringLen); - } -#elif defined(Q_OS_DARWIN) - // "kern.bootsessionuuid" is only available by name - char uuid[UuidStringLen + 1]; - size_t uuidlen = sizeof(uuid); - if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0 - && uuidlen == sizeof(uuid)) - return QByteArray(uuid, uuidlen - 1); -#endif - return QByteArray(); -}; - /*! \macro void Q_FALLTHROUGH() \relates <QtGlobal> |