Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsysinfo.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qsysinfo.h"
6
7#include <QtCore/qbytearray.h>
8#include <QtCore/qoperatingsystemversion.h>
9#include <QtCore/qstring.h>
10
11#include <private/qoperatingsystemversion_p.h>
12
13#ifdef Q_OS_UNIX
14# include <sys/utsname.h>
15# include <private/qcore_unix_p.h>
16#endif
17
18#ifdef Q_OS_ANDROID
19#include <QtCore/private/qjnihelpers_p.h>
20#include <qjniobject.h>
21#endif
22
23#if defined(Q_OS_SOLARIS)
24# include <sys/systeminfo.h>
25#endif
26
27#if defined(Q_OS_DARWIN)
28# include "qnamespace.h"
29# include <private/qcore_mac_p.h>
30# if __has_include(<IOKit/IOKitLib.h>)
31# include <IOKit/IOKitLib.h>
32# endif
33#endif
34
35#ifdef Q_OS_BSD4
36# include <sys/sysctl.h>
37#endif
38
39#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
41# include "private/qwinregistry_p.h"
42# include "qt_windows.h"
43#endif // Q_OS_WIN || Q_OS_CYGWIN
44
45#include "archdetect.cpp"
46
48
49using namespace Qt::StringLiterals;
50
89#if defined(Q_OS_DARWIN)
90
91static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
92{
93#ifdef Q_OS_MACOS
94 if (version.majorVersion() == 13)
95 return "Ventura";
96 if (version.majorVersion() == 12)
97 return "Monterey";
98 // Compare against predefined constant to handle 10.16/11.0
99 if (QOperatingSystemVersion::MacOSBigSur.version().isPrefixOf(version.version()))
100 return "Big Sur";
101 if (version.majorVersion() == 10) {
102 switch (version.minorVersion()) {
103 case 9:
104 return "Mavericks";
105 case 10:
106 return "Yosemite";
107 case 11:
108 return "El Capitan";
109 case 12:
110 return "Sierra";
111 case 13:
112 return "High Sierra";
113 case 14:
114 return "Mojave";
115 case 15:
116 return "Catalina";
117 }
118 }
119 // unknown, future version
120#else
121 Q_UNUSED(version);
122#endif
123 return nullptr;
124}
125
126#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
127
128# ifndef QT_BOOTSTRAPPED
129class QWindowsSockInit
130{
131public:
132 QWindowsSockInit();
133 ~QWindowsSockInit();
134 int version;
135};
136
137QWindowsSockInit::QWindowsSockInit()
138: version(0)
139{
140 //### should we try for 2.2 on all platforms ??
141 WSAData wsadata;
142
143 // IPv6 requires Winsock v2.0 or better.
144 if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) {
145 qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
146 } else {
147 version = 0x20;
148 }
149}
150
151QWindowsSockInit::~QWindowsSockInit()
152{
153 WSACleanup();
154}
155Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
156# endif // QT_BOOTSTRAPPED
157
158static QString readVersionRegistryString(const wchar_t *subKey)
159{
160 return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
161 .stringValue(subKey);
162}
163
164static inline QString windowsDisplayVersion()
165{
166 // https://tickets.puppetlabs.com/browse/FACT-3058
167 // The "ReleaseId" key stopped updating since Windows 10 20H2.
169 return readVersionRegistryString(L"DisplayVersion");
170 else
171 return readVersionRegistryString(L"ReleaseId");
172}
173
174static QString winSp_helper()
175{
176 const auto osv = qWindowsVersionInfo();
177 const qint16 major = osv.wServicePackMajor;
178 if (major) {
179 QString sp = QStringLiteral("SP ") + QString::number(major);
180 const qint16 minor = osv.wServicePackMinor;
181 if (minor)
182 sp += u'.' + QString::number(minor);
183
184 return sp;
185 }
186 return QString();
187}
188
189static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
190{
191 Q_UNUSED(version);
192 const OSVERSIONINFOEX osver = qWindowsVersionInfo();
193 const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
194
195#define Q_WINVER(major, minor) (major << 8 | minor)
196 switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
197 case Q_WINVER(10, 0):
198 if (workstation) {
199 if (osver.dwBuildNumber >= 22000)
200 return "11";
201 return "10";
202 }
203 // else: Server
204 if (osver.dwBuildNumber >= 20348)
205 return "Server 2022";
206 if (osver.dwBuildNumber >= 17763)
207 return "Server 2019";
208 return "Server 2016";
209 }
210#undef Q_WINVER
211 // unknown, future version
212 return nullptr;
213}
214
215#endif
216#if defined(Q_OS_UNIX)
217# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
218# define USE_ETC_OS_RELEASE
219struct QUnixOSVersion
220{
221 // from /etc/os-release older /etc/lsb-release // redhat /etc/redhat-release // debian /etc/debian_version
222 QString productType; // $ID $DISTRIB_ID // single line file containing: // Debian
223 QString productVersion; // $VERSION_ID $DISTRIB_RELEASE // <Vendor_ID release Version_ID> // single line file <Release_ID/sid>
224 QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION
225};
226
227static QString unquote(const char *begin, const char *end)
228{
229 // man os-release says:
230 // Variable assignment values must be enclosed in double
231 // or single quotes if they include spaces, semicolons or
232 // other special characters outside of A–Z, a–z, 0–9. Shell
233 // special characters ("$", quotes, backslash, backtick)
234 // must be escaped with backslashes, following shell style.
235 // All strings should be in UTF-8 format, and non-printable
236 // characters should not be used. It is not supported to
237 // concatenate multiple individually quoted strings.
238 if (*begin == '"')
239 return QString::fromUtf8(begin + 1, end - begin - 2);
240 return QString::fromUtf8(begin, end - begin);
241}
242static QByteArray getEtcFileContent(const char *filename)
243{
244 // we're avoiding QFile here
245 int fd = qt_safe_open(filename, O_RDONLY);
246 if (fd == -1)
247 return QByteArray();
248
249 QT_STATBUF sbuf;
250 if (QT_FSTAT(fd, &sbuf) == -1) {
252 return QByteArray();
253 }
254
255 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
256 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
258 return buffer;
259}
260
261static bool readEtcFile(QUnixOSVersion &v, const char *filename,
262 const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
263{
264
265 QByteArray buffer = getEtcFileContent(filename);
266 if (buffer.isEmpty())
267 return false;
268
269 const char *ptr = buffer.constData();
270 const char *end = buffer.constEnd();
271 const char *eol;
273 for (; ptr != end; ptr = eol + 1) {
274 // find the end of the line after ptr
275 eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
276 if (!eol)
277 eol = end - 1;
278 line.setRawData(ptr, eol - ptr);
279
280 if (line.startsWith(idKey)) {
281 ptr += idKey.size();
282 v.productType = unquote(ptr, eol);
283 continue;
284 }
285
286 if (line.startsWith(prettyNameKey)) {
287 ptr += prettyNameKey.size();
288 v.prettyName = unquote(ptr, eol);
289 continue;
290 }
291
292 if (line.startsWith(versionKey)) {
293 ptr += versionKey.size();
294 v.productVersion = unquote(ptr, eol);
295 continue;
296 }
297 }
298
299 return true;
300}
301
302static bool readOsRelease(QUnixOSVersion &v)
303{
304 QByteArray id = QByteArrayLiteral("ID=");
305 QByteArray versionId = QByteArrayLiteral("VERSION_ID=");
306 QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME=");
307
308 // man os-release(5) says:
309 // The file /etc/os-release takes precedence over /usr/lib/os-release.
310 // Applications should check for the former, and exclusively use its data
311 // if it exists, and only fall back to /usr/lib/os-release if it is
312 // missing.
313 return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) ||
314 readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName);
315}
316
317static bool readEtcLsbRelease(QUnixOSVersion &v)
318{
319 bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="),
320 QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION="));
321 if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
322 // some distributions have redundant information for the pretty name,
323 // so try /etc/<lowercasename>-release
324
325 // we're still avoiding QFile here
326 QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release";
327 int fd = qt_safe_open(distrorelease, O_RDONLY);
328 if (fd != -1) {
329 QT_STATBUF sbuf;
330 if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.size()) {
331 // file apparently contains interesting information
332 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
333 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
334 v.prettyName = QString::fromLatin1(buffer.trimmed());
335 }
337 }
338 }
339
340 // some distributions have a /etc/lsb-release file that does not provide the values
341 // we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
342 // Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
343 // returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
344 return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
345}
346
347#if defined(Q_OS_LINUX)
348static QByteArray getEtcFileFirstLine(const char *fileName)
349{
350 QByteArray buffer = getEtcFileContent(fileName);
351 if (buffer.isEmpty())
352 return QByteArray();
353
354 const char *ptr = buffer.constData();
355 return QByteArray(ptr, buffer.indexOf("\n")).trimmed();
356}
357
358static bool readEtcRedHatRelease(QUnixOSVersion &v)
359{
360 // /etc/redhat-release analysed should be a one line file
361 // the format of its content is <Vendor_ID release Version>
362 // i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
363 QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
364 if (line.isEmpty())
365 return false;
366
367 v.prettyName = QString::fromLatin1(line);
368
369 const char keyword[] = "release ";
370 const qsizetype releaseIndex = line.indexOf(keyword);
371 v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(u' ');
372 const qsizetype spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
373 v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
374 spaceIndex > -1 ? spaceIndex - releaseIndex - int(strlen(keyword)) : -1));
375 return true;
376}
377
378static bool readEtcDebianVersion(QUnixOSVersion &v)
379{
380 // /etc/debian_version analysed should be a one line file
381 // the format of its content is <Release_ID/sid>
382 // i.e. "jessie/sid"
383 QByteArray line = getEtcFileFirstLine("/etc/debian_version");
384 if (line.isEmpty())
385 return false;
386
387 v.productType = QStringLiteral("Debian");
388 v.productVersion = QString::fromLatin1(line);
389 return true;
390}
391#endif
392
393static bool findUnixOsVersion(QUnixOSVersion &v)
394{
395 if (readOsRelease(v))
396 return true;
397 if (readEtcLsbRelease(v))
398 return true;
399#if defined(Q_OS_LINUX)
400 if (readEtcRedHatRelease(v))
401 return true;
402 if (readEtcDebianVersion(v))
403 return true;
404#endif
405 return false;
406}
407# endif // USE_ETC_OS_RELEASE
408#endif // Q_OS_UNIX
409
410#ifdef Q_OS_ANDROID
411static const char *osVer_helper(QOperatingSystemVersion)
412{
413 // https://source.android.com/source/build-numbers.html
414 // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
415 const int sdk_int = QtAndroidPrivate::androidSdkVersion();
416 switch (sdk_int) {
417 case 3:
418 return "Cupcake";
419 case 4:
420 return "Donut";
421 case 5:
422 case 6:
423 case 7:
424 return "Eclair";
425 case 8:
426 return "Froyo";
427 case 9:
428 case 10:
429 return "Gingerbread";
430 case 11:
431 case 12:
432 case 13:
433 return "Honeycomb";
434 case 14:
435 case 15:
436 return "Ice Cream Sandwich";
437 case 16:
438 case 17:
439 case 18:
440 return "Jelly Bean";
441 case 19:
442 case 20:
443 return "KitKat";
444 case 21:
445 case 22:
446 return "Lollipop";
447 case 23:
448 return "Marshmallow";
449 case 24:
450 case 25:
451 return "Nougat";
452 case 26:
453 case 27:
454 return "Oreo";
455 case 28:
456 return "Pie";
457 case 29:
458 return "10";
459 case 30:
460 return "11";
461 case 31:
462 return "12";
463 case 32:
464 return "12L";
465 case 33:
466 return "13";
467 default:
468 break;
469 }
470
471 return "";
472}
473#endif
474
506{
508}
509
543{
544#if defined(Q_OS_WIN)
545 // We don't need to catch all the CPU architectures in this function;
546 // only those where the host CPU might be different than the build target
547 // (usually, 64-bit platforms).
548 SYSTEM_INFO info;
549 GetNativeSystemInfo(&info);
550 switch (info.wProcessorArchitecture) {
551# ifdef PROCESSOR_ARCHITECTURE_AMD64
552 case PROCESSOR_ARCHITECTURE_AMD64:
553 return QStringLiteral("x86_64");
554# endif
555# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
556 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
557# endif
558 case PROCESSOR_ARCHITECTURE_IA64:
559 return QStringLiteral("ia64");
560 }
561#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS)
562 // iOS-based OSes do not return the architecture on uname(2)'s result.
563 return buildCpuArchitecture();
564#elif defined(Q_OS_UNIX)
565 long ret = -1;
566 struct utsname u;
567
568# if defined(Q_OS_SOLARIS)
569 // We need a special call for Solaris because uname(2) on x86 returns "i86pc" for
570 // both 32- and 64-bit CPUs. Reference:
571 // http://docs.oracle.com/cd/E18752_01/html/816-5167/sysinfo-2.html#REFMAN2sysinfo-2
572 // http://fxr.watson.org/fxr/source/common/syscall/systeminfo.c?v=OPENSOLARIS
573 // http://fxr.watson.org/fxr/source/common/conf/param.c?v=OPENSOLARIS;im=10#L530
574 if (ret == -1)
575 ret = sysinfo(SI_ARCHITECTURE_64, u.machine, sizeof u.machine);
576# endif
577
578 if (ret == -1)
579 ret = uname(&u);
580
581 // we could use detectUnixVersion() above, but we only need a field no other function does
582 if (ret != -1) {
583 // the use of QT_BUILD_INTERNAL here is simply to ensure all branches build
584 // as we don't often build on some of the less common platforms
585# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
586 if (strcmp(u.machine, "aarch64") == 0)
587 return QStringLiteral("arm64");
588 if (strncmp(u.machine, "armv", 4) == 0)
589 return QStringLiteral("arm");
590# endif
591# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
592 // harmonize "powerpc" and "ppc" to "power"
593 if (strncmp(u.machine, "ppc", 3) == 0)
594 return "power"_L1 + QLatin1StringView(u.machine + 3);
595 if (strncmp(u.machine, "powerpc", 7) == 0)
596 return "power"_L1 + QLatin1StringView(u.machine + 7);
597 if (strcmp(u.machine, "Power Macintosh") == 0)
598 return "power"_L1;
599# endif
600# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
601 // Solaris sysinfo(2) (above) uses "sparcv9", but uname -m says "sun4u";
602 // Linux says "sparc64"
603 if (strcmp(u.machine, "sun4u") == 0 || strcmp(u.machine, "sparc64") == 0)
604 return QStringLiteral("sparcv9");
605 if (strcmp(u.machine, "sparc32") == 0)
606 return QStringLiteral("sparc");
607# endif
608# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
609 // harmonize all "i?86" to "i386"
610 if (strlen(u.machine) == 4 && u.machine[0] == 'i'
611 && u.machine[2] == '8' && u.machine[3] == '6')
612 return QStringLiteral("i386");
613 if (strcmp(u.machine, "amd64") == 0) // Solaris
614 return QStringLiteral("x86_64");
615# endif
616 return QString::fromLatin1(u.machine);
617 }
618#endif
619 return buildCpuArchitecture();
620}
621
657{
658 // ARCH_FULL is a concatenation of strings (incl. ARCH_PROCESSOR), which breaks
659 // QStringLiteral on MSVC. Since the concatenation behavior we want is specified
660 // the same C++11 paper as the Unicode strings, we'll use that macro and hope
661 // that Microsoft implements the new behavior when they add support for Unicode strings.
663}
664
666{
667 return QStringLiteral("unknown");
668}
669
694{
695#if defined(Q_OS_WIN)
696 return QStringLiteral("winnt");
697#elif defined(Q_OS_UNIX)
698 struct utsname u;
699 if (uname(&u) == 0)
700 return QString::fromLatin1(u.sysname).toLower();
701#endif
702 return unknownText();
703}
704
719{
720#ifdef Q_OS_WIN
721 const auto osver = QOperatingSystemVersion::current();
722 return QString::asprintf("%d.%d.%d",
723 osver.majorVersion(), osver.minorVersion(), osver.microVersion());
724#else
725 struct utsname u;
726 if (uname(&u) == 0)
727 return QString::fromLatin1(u.release);
728 return QString();
729#endif
730}
731
732
769{
770 // similar, but not identical to QFileSelectorPrivate::platformSelectors
771#if defined(Q_OS_WIN)
772 return QStringLiteral("windows");
773
774#elif defined(Q_OS_QNX)
775 return QStringLiteral("qnx");
776
777#elif defined(Q_OS_ANDROID)
778 return QStringLiteral("android");
779
780#elif defined(Q_OS_IOS)
781 return QStringLiteral("ios");
782#elif defined(Q_OS_TVOS)
783 return QStringLiteral("tvos");
784#elif defined(Q_OS_WATCHOS)
785 return QStringLiteral("watchos");
786#elif defined(Q_OS_MACOS)
787 return QStringLiteral("macos");
788#elif defined(Q_OS_DARWIN)
789 return QStringLiteral("darwin");
790#elif defined(Q_OS_WASM)
791 return QStringLiteral("wasm");
792
793#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
794 QUnixOSVersion unixOsVersion;
795 findUnixOsVersion(unixOsVersion);
796 if (!unixOsVersion.productType.isEmpty())
797 return unixOsVersion.productType;
798#endif
799 return unknownText();
800}
801
837{
838#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
839 const auto version = QOperatingSystemVersion::current();
840 return QString::asprintf("%d.%d", version.majorVersion(), version.minorVersion());
841#elif defined(Q_OS_WIN)
842 const char *version = osVer_helper();
843 if (version) {
844 const QLatin1Char spaceChar(' ');
845 return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
846 }
847 // fall through
848
849#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
850 QUnixOSVersion unixOsVersion;
851 findUnixOsVersion(unixOsVersion);
852 if (!unixOsVersion.productVersion.isEmpty())
853 return unixOsVersion.productVersion;
854#endif
855
856 // fallback
857 return unknownText();
858}
859
875{
876#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
877 const auto version = QOperatingSystemVersion::current();
878 const int majorVersion = version.majorVersion();
879 const QString versionString = QString::asprintf("%d.%d", majorVersion, version.minorVersion());
880 QString result = version.name() + u' ';
881 const char *name = osVer_helper(version);
882 if (!name)
883 return result + versionString;
885# if !defined(Q_OS_WIN)
886 return result + " ("_L1 + versionString + u')';
887# else
888 // (resembling winver.exe): Windows 10 "Windows 10 Version 1809"
889 const auto displayVersion = windowsDisplayVersion();
890 if (!displayVersion.isEmpty())
891 result += " Version "_L1 + displayVersion;
892 return result;
893# endif // Windows
894#elif defined(Q_OS_HAIKU)
895 return "Haiku "_L1 + productVersion();
896#elif defined(Q_OS_UNIX)
897# ifdef USE_ETC_OS_RELEASE
898 QUnixOSVersion unixOsVersion;
899 findUnixOsVersion(unixOsVersion);
900 if (!unixOsVersion.prettyName.isEmpty())
901 return unixOsVersion.prettyName;
902# endif
903 struct utsname u;
904 if (uname(&u) == 0)
905 return QString::fromLatin1(u.sysname) + u' ' + QString::fromLatin1(u.release);
906#endif
907 return unknownText();
908}
909
910#ifndef QT_BOOTSTRAPPED
927{
928 // the hostname can change, so we can't cache it
929#if defined(Q_OS_LINUX)
930 // gethostname(3) on Linux just calls uname(2), so do it ourselves
931 // and avoid a memcpy
932 struct utsname u;
933 if (uname(&u) == 0)
934 return QString::fromLocal8Bit(u.nodename);
935 return QString();
936#else
937# ifdef Q_OS_WIN
938 // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
939 winsockInit();
940 QString hostName;
941 hostName.resize(512);
942 unsigned long len = hostName.size();
943 BOOL res = GetComputerNameEx(ComputerNameDnsHostname,
944 reinterpret_cast<wchar_t *>(const_cast<quint16 *>(hostName.utf16())), &len);
945 if (!res && len > 512) {
946 hostName.resize(len - 1);
947 GetComputerNameEx(ComputerNameDnsHostname,
948 reinterpret_cast<wchar_t *>(const_cast<quint16 *>(hostName.utf16())), &len);
949 }
950 hostName.truncate(len);
951 return hostName;
952# else // !Q_OS_WIN
953
954 char hostName[512];
955 if (gethostname(hostName, sizeof(hostName)) == -1)
956 return QString();
957 hostName[sizeof(hostName) - 1] = '\0';
958 return QString::fromLocal8Bit(hostName);
959# endif
960#endif
961}
962#endif // QT_BOOTSTRAPPED
963
964enum {
965 UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1
967
991{
992#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
993 char uuid[UuidStringLen + 1];
994 static const mach_port_t defaultPort = 0; // Effectively kIOMasterPortDefault/kIOMainPortDefault
995 io_service_t service = IOServiceGetMatchingService(defaultPort, IOServiceMatching("IOPlatformExpertDevice"));
996 QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
997 CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
998 return QByteArray(uuid);
999#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID)
1000 char uuid[UuidStringLen + 1];
1001 size_t uuidlen = sizeof(uuid);
1002 int name[] = { CTL_KERN, KERN_HOSTUUID };
1003 if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0
1004 && uuidlen == sizeof(uuid))
1005 return QByteArray(uuid, uuidlen - 1);
1006#elif defined(Q_OS_UNIX)
1007 // The modern name on Linux is /etc/machine-id, but that path is
1008 // unlikely to exist on non-Linux (non-systemd) systems. The old
1009 // path is more than enough.
1010 static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id";
1011 const char *firstfilename = fullfilename + sizeof("/usr/local") - 1;
1012 int fd = qt_safe_open(firstfilename, O_RDONLY);
1013 if (fd == -1 && errno == ENOENT)
1014 fd = qt_safe_open(fullfilename, O_RDONLY);
1015
1016 if (fd != -1) {
1017 char buffer[32]; // 128 bits, hex-encoded
1018 qint64 len = qt_safe_read(fd, buffer, sizeof(buffer));
1020
1021 if (len != -1)
1022 return QByteArray(buffer, len);
1023 }
1024#elif defined(Q_OS_WIN)
1025 // Let's poke at the registry
1026 const QString machineGuid = QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Cryptography)")
1027 .stringValue(u"MachineGuid"_s);
1028 if (!machineGuid.isEmpty())
1029 return machineGuid.toLatin1();
1030#endif
1031 return QByteArray();
1032}
1033
1048{
1049#ifdef Q_OS_LINUX
1050 // use low-level API here for simplicity
1051 int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY);
1052 if (fd != -1) {
1053 char uuid[UuidStringLen];
1054 qint64 len = qt_safe_read(fd, uuid, sizeof(uuid));
1056 if (len == UuidStringLen)
1057 return QByteArray(uuid, UuidStringLen);
1058 }
1059#elif defined(Q_OS_DARWIN)
1060 // "kern.bootsessionuuid" is only available by name
1061 char uuid[UuidStringLen + 1];
1062 size_t uuidlen = sizeof(uuid);
1063 if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0
1064 && uuidlen == sizeof(uuid))
1065 return QByteArray(uuid, uuidlen - 1);
1066#endif
1067 return QByteArray();
1068};
1069
#define ARCH_PROCESSOR
#define ARCH_FULL
\inmodule QtCore
Definition qbytearray.h:57
QByteArray trimmed() const &
Definition qbytearray.h:198
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
QByteArray toLower() const &
Definition qbytearray.h:190
static QOperatingSystemVersion current()
[0]
static constexpr QOperatingSystemVersionBase Windows10_20H2
\variable QOperatingSystemVersion::Windows10_20H2
static constexpr QOperatingSystemVersionBase MacOSBigSur
\variable QOperatingSystemVersion::MacOSBigSur
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6737
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString toLower() const &
Definition qstring.h:368
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QString & setRawData(const QChar *unicode, qsizetype size)
Definition qstring.cpp:9261
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3435
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition qstring.cpp:7005
void resize(qsizetype size)
Sets the size of the string to size characters.
Definition qstring.cpp:2654
static QString currentCpuArchitecture()
Definition qsysinfo.cpp:542
static QByteArray bootUniqueId()
static QString buildAbi()
Definition qsysinfo.cpp:656
static QByteArray machineUniqueId()
Definition qsysinfo.cpp:990
static QString kernelVersion()
Definition qsysinfo.cpp:718
static QString machineHostName()
Definition qsysinfo.cpp:926
static QString productType()
Definition qsysinfo.cpp:768
static QString kernelType()
Definition qsysinfo.cpp:693
static QString buildCpuArchitecture()
Definition qsysinfo.cpp:505
static QString productVersion()
Definition qsysinfo.cpp:836
static QString prettyProductName()
Definition qsysinfo.cpp:874
QString stringValue(QStringView subKey) const
Combined button and popup list for selecting options.
Q_CORE_EXPORT jint androidSdkVersion()
constexpr Initialization Uninitialized
QString eol
Definition language.cpp:58
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
static int qt_safe_close(int fd)
static QString unquote(QStringView str)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
return ret
static ControlElement< T > * ptr(QWidget *widget)
GLsizei const GLfloat * v
[13]
GLuint GLuint end
GLenum GLuint buffer
GLuint64 GLenum GLint fd
GLuint name
GLuint res
GLenum GLsizei len
GLuint64EXT * result
[6]
OSVERSIONINFOEX qWindowsVersionInfo()
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define QStringLiteral(str)
static QString unknownText()
Definition qsysinfo.cpp:665
@ UuidStringLen
Definition qsysinfo.cpp:965
#define sp
#define Q_UNUSED(x)
short qint16
Definition qtypes.h:42
unsigned short quint16
Definition qtypes.h:43
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFileInfo info(fileName)
[8]
\inmodule QtCore \reentrant
Definition qchar.h:17