8#include <QtCore/qbytearray.h>
9#include <QtCore/qoperatingsystemversion.h>
10#include <QtCore/qstring.h>
12#include <private/qoperatingsystemversion_p.h>
15# include <sys/utsname.h>
16# include <private/qcore_unix_p.h>
20#include <QtCore/private/qjnihelpers_p.h>
21#include <qjniobject.h>
24#if defined(Q_OS_HARMONY)
25#include <deviceinfo.h>
28#if defined(Q_OS_SOLARIS)
29# include <sys/systeminfo.h>
32#if defined(Q_OS_DARWIN)
33# include "qnamespace.h"
34# include <private/qcore_mac_p.h>
35# if __has_include(<IOKit/IOKitLib.h>)
36# include <IOKit/IOKitLib.h>
41# include <sys/sysctl.h>
45# include "qoperatingsystemversion_win_p.h"
46# include "private/qwinregistry_p.h"
47# include "qt_windows.h"
54using namespace Qt::StringLiterals;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
76
77
78
79
80
81
82
83
86
87
88
89
90
91
92
94#if defined(Q_OS_DARWIN)
96static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
99 switch (version.majorVersion()) {
101 switch (version.minorVersion()) {
102 case 9:
return "Mavericks";
103 case 10:
return "Yosemite";
104 case 11:
return "El Capitan";
105 case 12:
return "Sierra";
106 case 13:
return "High Sierra";
107 case 14:
return "Mojave";
108 case 15:
return "Catalina";
109 case 16:
return "Big Sur";
114 case 11:
return "Big Sur";
115 case 12:
return "Monterey";
116 case 13:
return "Ventura";
117 case 14:
return "Sonoma";
118 case 15:
return "Sequoia";
119 case 26:
return "Tahoe";
120 case 27:
return "Golden Gate";
131#elif defined(Q_OS_WIN)
133# ifndef QT_BOOTSTRAPPED
134class QWindowsSockInit
142QWindowsSockInit::QWindowsSockInit()
147 if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
148 qWarning(
"QTcpSocketAPI: WinSock v2.2 initialization failed.");
154QWindowsSockInit::~QWindowsSockInit()
158Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
161static QString readVersionRegistryString(
const wchar_t *subKey)
163 return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
164 .stringValue(subKey);
167static inline QString windowsDisplayVersion()
171 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10_20H2)
172 return readVersionRegistryString(L"DisplayVersion");
174 return readVersionRegistryString(L"ReleaseId");
177static QString winSp_helper()
179 const auto osv = qWindowsVersionInfo();
180 const qint16 major = osv.wServicePackMajor;
182 QString sp = QStringLiteral(
"SP ") + QString::number(major);
183 const qint16 minor = osv.wServicePackMinor;
185 sp += u'.' + QString::number(minor);
192static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
195 const OSVERSIONINFOEX osver = qWindowsVersionInfo();
196 const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
198#define Q_WINVER(major, minor) (major << 8
| minor)
199 switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
200 case Q_WINVER(10, 0):
202 if (osver.dwBuildNumber >= 22000)
207 if (osver.dwBuildNumber >= 26100)
208 return "Server 2025";
209 if (osver.dwBuildNumber >= 20348)
210 return "Server 2022";
211 if (osver.dwBuildNumber >= 17763)
212 return "Server 2019";
213 return "Server 2016";
221#if defined(Q_OS_UNIX)
222# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
223# define USE_ETC_OS_RELEASE
228 QString productVersion;
232static QString unquote(QByteArrayView str)
243 if (str.size() >= 2 && str.front() ==
'"' && str.back() ==
'"')
244 str = str.sliced(1).chopped(1);
245 return QString::fromUtf8(str);
248static QByteArray getEtcFileContent(
const char *filename)
251 int fd = qt_safe_open(filename, O_RDONLY);
256 if (QT_FSTAT(fd, &sbuf) == -1) {
261 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
262 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
267static bool readEtcFile(QUnixOSVersion &v,
const char *filename,
268 const QByteArray &idKey,
const QByteArray &versionKey,
const QByteArray &prettyNameKey)
271 QByteArray buffer = getEtcFileContent(filename);
272 if (buffer.isEmpty())
275 const char *ptr = buffer.constData();
276 const char *end = buffer.constEnd();
279 for (; ptr != end; ptr = eol + 1) {
281 eol =
static_cast<
const char *>(memchr(ptr,
'\n', end - ptr));
284 line.setRawData(ptr, eol - ptr);
286 if (line.startsWith(idKey)) {
288 v.productType = unquote({ptr, eol});
292 if (line.startsWith(prettyNameKey)) {
293 ptr += prettyNameKey.size();
294 v.prettyName = unquote({ptr, eol});
298 if (line.startsWith(versionKey)) {
299 ptr += versionKey.size();
300 v.productVersion = unquote({ptr, eol});
308static bool readOsRelease(QUnixOSVersion &v)
310 QByteArray id = QByteArrayLiteral(
"ID=");
311 QByteArray versionId = QByteArrayLiteral(
"VERSION_ID=");
312 QByteArray prettyName = QByteArrayLiteral(
"PRETTY_NAME=");
319 return readEtcFile(v,
"/etc/os-release", id, versionId, prettyName) ||
320 readEtcFile(v,
"/usr/lib/os-release", id, versionId, prettyName);
323static bool readEtcLsbRelease(QUnixOSVersion &v)
325 bool ok = readEtcFile(v,
"/etc/lsb-release", QByteArrayLiteral(
"DISTRIB_ID="),
326 QByteArrayLiteral(
"DISTRIB_RELEASE="), QByteArrayLiteral(
"DISTRIB_DESCRIPTION="));
327 if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
332 QByteArray distrorelease =
"/etc/" + v.productType.toLatin1().toLower() +
"-release";
333 int fd = qt_safe_open(distrorelease, O_RDONLY);
336 if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.size()) {
338 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
339 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
340 v.prettyName = QString::fromLatin1(buffer.trimmed());
350 return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
353#if defined(Q_OS_LINUX)
354static bool readEtcRedHatRelease(QUnixOSVersion &v)
359 QByteArray line = getEtcFileContent(
"/etc/redhat-release").trimmed();
363 v.prettyName = QString::fromLatin1(line);
365 const char keyword[] =
"release ";
366 const qsizetype releaseIndex = line.indexOf(keyword);
367 v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(u' ');
368 const qsizetype spaceIndex = line.indexOf(
' ', releaseIndex + strlen(keyword));
369 v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
370 spaceIndex > -1 ? spaceIndex - releaseIndex -
int(strlen(keyword)) : -1));
374static bool readEtcDebianVersion(QUnixOSVersion &v)
379 QByteArray line = getEtcFileContent(
"/etc/debian_version").trimmed();
383 v.productType = QStringLiteral(
"Debian");
384 v.productVersion = QString::fromLatin1(line);
389[[maybe_unused]]
static bool findUnixOsVersion(QUnixOSVersion &v)
391 if (readOsRelease(v))
393 if (readEtcLsbRelease(v))
395#if defined(Q_OS_LINUX)
396 if (readEtcRedHatRelease(v))
398 if (readEtcDebianVersion(v))
407static const char *osVer_helper(QOperatingSystemVersion)
411 const int sdk_int = QtAndroidPrivate::androidSdkVersion();
425 return "Gingerbread";
432 return "Ice Cream Sandwich";
444 return "Marshmallow";
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501QString QSysInfo::buildCpuArchitecture()
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538QString QSysInfo::currentCpuArchitecture()
545 GetNativeSystemInfo(&info);
546 switch (info.wProcessorArchitecture) {
547# ifdef PROCESSOR_ARCHITECTURE_AMD64
548 case PROCESSOR_ARCHITECTURE_AMD64:
549 return QStringLiteral(
"x86_64");
551# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
552 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
554 case PROCESSOR_ARCHITECTURE_IA64:
555 return QStringLiteral(
"ia64");
557#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS)
559 return buildCpuArchitecture();
560#elif defined(Q_OS_UNIX)
564# if defined(Q_OS_SOLARIS)
571 ret = sysinfo(SI_ARCHITECTURE_64, u.machine,
sizeof u.machine);
581# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
582 if (strcmp(u.machine,
"aarch64") == 0)
583 return QStringLiteral(
"arm64");
584 if (strncmp(u.machine,
"armv", 4) == 0)
585 return QStringLiteral(
"arm");
587# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
589 if (strncmp(u.machine,
"ppc", 3) == 0)
590 return "power"_L1 + QLatin1StringView(u.machine + 3);
591 if (strncmp(u.machine,
"powerpc", 7) == 0)
592 return "power"_L1 + QLatin1StringView(u.machine + 7);
593 if (strcmp(u.machine,
"Power Macintosh") == 0)
596# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
599 if (strcmp(u.machine,
"sun4u") == 0 || strcmp(u.machine,
"sparc64") == 0)
600 return QStringLiteral(
"sparcv9");
601 if (strcmp(u.machine,
"sparc32") == 0)
602 return QStringLiteral(
"sparc");
604# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
606 if (strlen(u.machine) == 4 && u.machine[0] ==
'i'
607 && u.machine[2] ==
'8' && u.machine[3] ==
'6')
608 return QStringLiteral(
"i386");
609 if (strcmp(u.machine,
"amd64") == 0)
610 return QStringLiteral(
"x86_64");
612 return QString::fromLatin1(u.machine);
615 return buildCpuArchitecture();
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652QString QSysInfo::buildAbi()
663 return QStringLiteral(
"unknown");
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689QString QSysInfo::kernelType()
692 return QStringLiteral(
"winnt");
693#elif defined(Q_OS_UNIX)
696 return QString::fromLatin1(u.sysname).toLower();
698 return unknownText();
702
703
704
705
706
707
708
709
710
711
712
713
714
715QString QSysInfo::kernelVersion()
718 const auto osver = QOperatingSystemVersion::current();
719 return QString::asprintf(
"%d.%d.%d",
720 osver.majorVersion(), osver.minorVersion(), osver.microVersion());
723 if (uname(&u) == 0) {
726 auto versionStr = QByteArrayView(u.kernelversion);
727 if (
auto lastSpace = versionStr.lastIndexOf(
' '); lastSpace != -1) {
728 return QString::fromLatin1(versionStr.sliced(lastSpace + 1));
731 return QString::fromLatin1(u.release);
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776QString QSysInfo::productType()
780 return QStringLiteral(
"windows");
782#elif defined(Q_OS_QNX)
783 return QStringLiteral(
"qnx");
785#elif defined(Q_OS_ANDROID)
786 return QStringLiteral(
"android");
788#elif defined(Q_OS_HARMONY)
789 return QStringLiteral(
"harmonyos");
790#elif defined(Q_OS_IOS)
791 return QStringLiteral(
"ios");
792#elif defined(Q_OS_TVOS)
793 return QStringLiteral(
"tvos");
794#elif defined(Q_OS_WATCHOS)
795 return QStringLiteral(
"watchos");
796#elif defined(Q_OS_VISIONOS)
797 return QStringLiteral(
"visionos");
798#elif defined(Q_OS_MACOS)
799 return QStringLiteral(
"macos");
800#elif defined(Q_OS_DARWIN)
801 return QStringLiteral(
"darwin");
802#elif defined(Q_OS_WASM)
803 return QStringLiteral(
"wasm");
804#elif defined(Q_OS_VXWORKS)
805 return QStringLiteral(
"vxworks");
807#elif defined(USE_ETC_OS_RELEASE)
808 QUnixOSVersion unixOsVersion;
809 findUnixOsVersion(unixOsVersion);
810 if (!unixOsVersion.productType.isEmpty())
811 return unixOsVersion.productType;
813 return unknownText();
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851QString QSysInfo::productVersion()
853#if defined(Q_OS_ANDROID)
854 const auto version = QOperatingSystemVersion::current();
855 return QString::asprintf(
"%d.%d", version.majorVersion(), version.minorVersion());
856#elif defined(Q_OS_DARWIN) || defined(Q_OS_HARMONY)
857 const auto version = QOperatingSystemVersion::current();
858 return QString::asprintf(
"%d.%d.%d", version.majorVersion(),
859 version.minorVersion(),
860 version.microVersion());
861#elif defined(Q_OS_WIN)
862 const char *version = osVer_helper();
864 const QLatin1Char spaceChar(
' ');
865 return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
869#elif defined(Q_OS_VXWORKS)
872 return QString::fromLatin1(u.releaseversion);
875#elif defined(USE_ETC_OS_RELEASE)
876 QUnixOSVersion unixOsVersion;
877 findUnixOsVersion(unixOsVersion);
878 if (!unixOsVersion.productVersion.isEmpty())
879 return unixOsVersion.productVersion;
883 return unknownText();
887
888
889
890
891
892
893
894
895
896
897
898
899
900QString QSysInfo::prettyProductName()
902#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
903 const auto version = QOperatingSystemVersion::current();
904 QString versionString;
905# if defined(Q_OS_DARWIN)
906 if (
const int microVersion = version.microVersion(); microVersion > 0)
907 versionString = QString::asprintf(
"%d.%d.%d", version.majorVersion(),
908 version.minorVersion(),
912 versionString = QString::asprintf(
"%d.%d", version.majorVersion(),
913 version.minorVersion());
914 QString result = version.name() + u' ';
915 const char *name = osVer_helper(version);
917 return result + versionString;
918 result += QLatin1StringView(name);
919# if !defined(Q_OS_WIN)
920 return result +
" ("_L1 + versionString + u')';
923 const auto displayVersion = windowsDisplayVersion();
924 if (!displayVersion.isEmpty())
925 result +=
" Version "_L1 + displayVersion;
928#elif defined(Q_OS_HARMONY)
929 QString result = QString::asprintf(
"%s %s", OH_GetOSFullName(),
930 OH_GetDistributionOSReleaseType());
932#elif defined(Q_OS_HAIKU)
933 return "Haiku "_L1 + productVersion();
934#elif defined(Q_OS_UNIX)
935# ifdef USE_ETC_OS_RELEASE
936 QUnixOSVersion unixOsVersion;
937 findUnixOsVersion(unixOsVersion);
938 if (!unixOsVersion.prettyName.isEmpty())
939 return unixOsVersion.prettyName;
943 return QString::fromLatin1(u.sysname) + u' ' + QString::fromLatin1(u.release);
945 return unknownText();
948#ifndef QT_BOOTSTRAPPED
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964QString QSysInfo::machineHostName()
967#if defined(Q_OS_LINUX)
972 return QString::fromLocal8Bit(u.nodename);
979 hostName.resize(512);
980 unsigned long len = hostName.size();
981 BOOL res = GetComputerNameEx(ComputerNameDnsHostname,
982 reinterpret_cast<
wchar_t *>(hostName.data()), &len);
983 if (!res && len > 512) {
984 hostName.resize(len - 1);
985 GetComputerNameEx(ComputerNameDnsHostname,
reinterpret_cast<
wchar_t *>(hostName.data()),
988 hostName.truncate(len);
993 if (gethostname(hostName,
sizeof(hostName)) == -1)
995 hostName[
sizeof(hostName) - 1] =
'\0';
996 return QString::fromLocal8Bit(hostName);
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028QByteArray QSysInfo::machineUniqueId()
1030#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
1031 char uuid[UuidStringLen + 1];
1032 io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching(
"IOPlatformExpertDevice"));
1033 QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
1034 CFStringGetCString(stringRef, uuid,
sizeof(uuid), kCFStringEncodingMacRoman);
1035 return QByteArray(uuid);
1036#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID)
1037 char uuid[UuidStringLen + 1];
1038 size_t uuidlen =
sizeof(uuid);
1039 int name[] = { CTL_KERN, KERN_HOSTUUID };
1040 if (sysctl(name,
sizeof name /
sizeof name[0], &uuid, &uuidlen,
nullptr, 0) == 0
1041 && uuidlen ==
sizeof(uuid))
1042 return QByteArray(uuid, uuidlen - 1);
1043#elif defined(Q_OS_UNIX)
1047 static const char fullfilename[] =
"/usr/local/var/lib/dbus/machine-id";
1048 const char *firstfilename = fullfilename +
sizeof(
"/usr/local") - 1;
1049 int fd = qt_safe_open(firstfilename, O_RDONLY);
1050 if (fd == -1 && errno == ENOENT)
1051 fd = qt_safe_open(fullfilename, O_RDONLY);
1055 qint64 len = qt_safe_read(fd, buffer,
sizeof(buffer));
1059 return QByteArray(buffer, len);
1061#elif defined(Q_OS_WIN)
1063 const QString machineGuid = QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Cryptography)")
1064 .stringValue(L"MachineGuid");
1065 if (!machineGuid.isEmpty())
1066 return machineGuid.toLatin1();
1068 return QByteArray();
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084QByteArray QSysInfo::bootUniqueId()
1088 int fd = qt_safe_open(
"/proc/sys/kernel/random/boot_id", O_RDONLY);
1090 char uuid[UuidStringLen];
1091 qint64 len = qt_safe_read(fd, uuid,
sizeof(uuid));
1093 if (len == UuidStringLen)
1094 return QByteArray(uuid, UuidStringLen);
1096#elif defined(Q_OS_DARWIN)
1098 char uuid[UuidStringLen + 1];
1099 size_t uuidlen =
sizeof(uuid);
1100 if (sysctlbyname(
"kern.bootsessionuuid", uuid, &uuidlen,
nullptr, 0) == 0
1101 && uuidlen ==
sizeof(uuid))
1102 return QByteArray(uuid, uuidlen - 1);
1104 return QByteArray();
Combined button and popup list for selecting options.
static QString unknownText()