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_SOLARIS)
25# include <sys/systeminfo.h>
28#if defined(Q_OS_DARWIN)
29# include "qnamespace.h"
30# include <private/qcore_mac_p.h>
31# if __has_include(<IOKit/IOKitLib.h>)
32# include <IOKit/IOKitLib.h>
37# include <sys/sysctl.h>
41# include "qoperatingsystemversion_win_p.h"
42# include "private/qwinregistry_p.h"
43# include "qt_windows.h"
50using namespace Qt::StringLiterals;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
72
73
74
75
76
77
78
79
82
83
84
85
86
87
88
90#if defined(Q_OS_DARWIN)
92static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
95 switch (version.majorVersion()) {
97 switch (version.minorVersion()) {
98 case 9:
return "Mavericks";
99 case 10:
return "Yosemite";
100 case 11:
return "El Capitan";
101 case 12:
return "Sierra";
102 case 13:
return "High Sierra";
103 case 14:
return "Mojave";
104 case 15:
return "Catalina";
105 case 16:
return "Big Sur";
110 case 11:
return "Big Sur";
111 case 12:
return "Monterey";
112 case 13:
return "Ventura";
113 case 14:
return "Sonoma";
114 case 15:
return "Sequoia";
115 case 26:
return "Tahoe";
126#elif defined(Q_OS_WIN)
128# ifndef QT_BOOTSTRAPPED
129class QWindowsSockInit
137QWindowsSockInit::QWindowsSockInit()
142 if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
143 qWarning(
"QTcpSocketAPI: WinSock v2.2 initialization failed.");
149QWindowsSockInit::~QWindowsSockInit()
153Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
156static QString readVersionRegistryString(
const wchar_t *subKey)
158 return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
159 .stringValue(subKey);
162static inline QString windowsDisplayVersion()
166 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10_20H2)
167 return readVersionRegistryString(L"DisplayVersion");
169 return readVersionRegistryString(L"ReleaseId");
172static QString winSp_helper()
174 const auto osv = qWindowsVersionInfo();
175 const qint16 major = osv.wServicePackMajor;
177 QString sp = QStringLiteral(
"SP ") + QString::number(major);
178 const qint16 minor = osv.wServicePackMinor;
180 sp += u'.' + QString::number(minor);
187static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
190 const OSVERSIONINFOEX osver = qWindowsVersionInfo();
191 const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
193#define Q_WINVER(major, minor) (major << 8
| minor)
194 switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
195 case Q_WINVER(10, 0):
197 if (osver.dwBuildNumber >= 22000)
202 if (osver.dwBuildNumber >= 26100)
203 return "Server 2025";
204 if (osver.dwBuildNumber >= 20348)
205 return "Server 2022";
206 if (osver.dwBuildNumber >= 17763)
207 return "Server 2019";
208 return "Server 2016";
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
223 QString productVersion;
227static QString unquote(QByteArrayView str)
238 if (str.size() >= 2 && str.front() ==
'"' && str.back() ==
'"')
239 str = str.sliced(1).chopped(1);
240 return QString::fromUtf8(str);
243static QByteArray getEtcFileContent(
const char *filename)
246 int fd = qt_safe_open(filename, O_RDONLY);
251 if (QT_FSTAT(fd, &sbuf) == -1) {
256 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
257 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
262static bool readEtcFile(QUnixOSVersion &v,
const char *filename,
263 const QByteArray &idKey,
const QByteArray &versionKey,
const QByteArray &prettyNameKey)
266 QByteArray buffer = getEtcFileContent(filename);
267 if (buffer.isEmpty())
270 const char *ptr = buffer.constData();
271 const char *end = buffer.constEnd();
274 for (; ptr != end; ptr = eol + 1) {
276 eol =
static_cast<
const char *>(memchr(ptr,
'\n', end - ptr));
279 line.setRawData(ptr, eol - ptr);
281 if (line.startsWith(idKey)) {
283 v.productType = unquote({ptr, eol});
287 if (line.startsWith(prettyNameKey)) {
288 ptr += prettyNameKey.size();
289 v.prettyName = unquote({ptr, eol});
293 if (line.startsWith(versionKey)) {
294 ptr += versionKey.size();
295 v.productVersion = unquote({ptr, eol});
303static bool readOsRelease(QUnixOSVersion &v)
305 QByteArray id = QByteArrayLiteral(
"ID=");
306 QByteArray versionId = QByteArrayLiteral(
"VERSION_ID=");
307 QByteArray prettyName = QByteArrayLiteral(
"PRETTY_NAME=");
314 return readEtcFile(v,
"/etc/os-release", id, versionId, prettyName) ||
315 readEtcFile(v,
"/usr/lib/os-release", id, versionId, prettyName);
318static bool readEtcLsbRelease(QUnixOSVersion &v)
320 bool ok = readEtcFile(v,
"/etc/lsb-release", QByteArrayLiteral(
"DISTRIB_ID="),
321 QByteArrayLiteral(
"DISTRIB_RELEASE="), QByteArrayLiteral(
"DISTRIB_DESCRIPTION="));
322 if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
327 QByteArray distrorelease =
"/etc/" + v.productType.toLatin1().toLower() +
"-release";
328 int fd = qt_safe_open(distrorelease, O_RDONLY);
331 if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.size()) {
333 QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
334 buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
335 v.prettyName = QString::fromLatin1(buffer.trimmed());
345 return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
348#if defined(Q_OS_LINUX)
349static QByteArray getEtcFileFirstLine(
const char *fileName)
351 QByteArray buffer = getEtcFileContent(fileName);
352 if (buffer.isEmpty())
355 const char *ptr = buffer.constData();
356 return QByteArray(ptr, buffer.indexOf(
"\n")).trimmed();
359static bool readEtcRedHatRelease(QUnixOSVersion &v)
364 QByteArray line = getEtcFileFirstLine(
"/etc/redhat-release");
368 v.prettyName = QString::fromLatin1(line);
370 const char keyword[] =
"release ";
371 const qsizetype releaseIndex = line.indexOf(keyword);
372 v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(u' ');
373 const qsizetype spaceIndex = line.indexOf(
' ', releaseIndex + strlen(keyword));
374 v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
375 spaceIndex > -1 ? spaceIndex - releaseIndex -
int(strlen(keyword)) : -1));
379static bool readEtcDebianVersion(QUnixOSVersion &v)
384 QByteArray line = getEtcFileFirstLine(
"/etc/debian_version");
388 v.productType = QStringLiteral(
"Debian");
389 v.productVersion = QString::fromLatin1(line);
394static bool findUnixOsVersion(QUnixOSVersion &v)
396 if (readOsRelease(v))
398 if (readEtcLsbRelease(v))
400#if defined(Q_OS_LINUX)
401 if (readEtcRedHatRelease(v))
403 if (readEtcDebianVersion(v))
412static const char *osVer_helper(QOperatingSystemVersion)
416 const int sdk_int = QtAndroidPrivate::androidSdkVersion();
430 return "Gingerbread";
437 return "Ice Cream Sandwich";
449 return "Marshmallow";
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506QString QSysInfo::buildCpuArchitecture()
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
538
539
540
541
542
543QString QSysInfo::currentCpuArchitecture()
550 GetNativeSystemInfo(&info);
551 switch (info.wProcessorArchitecture) {
552# ifdef PROCESSOR_ARCHITECTURE_AMD64
553 case PROCESSOR_ARCHITECTURE_AMD64:
554 return QStringLiteral(
"x86_64");
556# ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
557 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
559 case PROCESSOR_ARCHITECTURE_IA64:
560 return QStringLiteral(
"ia64");
562#elif defined(Q_OS_DARWIN) && !defined(Q_OS_MACOS)
564 return buildCpuArchitecture();
565#elif defined(Q_OS_UNIX)
569# if defined(Q_OS_SOLARIS)
576 ret = sysinfo(SI_ARCHITECTURE_64, u.machine,
sizeof u.machine);
586# if defined(Q_PROCESSOR_ARM) || defined(QT_BUILD_INTERNAL)
587 if (strcmp(u.machine,
"aarch64") == 0)
588 return QStringLiteral(
"arm64");
589 if (strncmp(u.machine,
"armv", 4) == 0)
590 return QStringLiteral(
"arm");
592# if defined(Q_PROCESSOR_POWER) || defined(QT_BUILD_INTERNAL)
594 if (strncmp(u.machine,
"ppc", 3) == 0)
595 return "power"_L1 + QLatin1StringView(u.machine + 3);
596 if (strncmp(u.machine,
"powerpc", 7) == 0)
597 return "power"_L1 + QLatin1StringView(u.machine + 7);
598 if (strcmp(u.machine,
"Power Macintosh") == 0)
601# if defined(Q_PROCESSOR_SPARC) || defined(QT_BUILD_INTERNAL)
604 if (strcmp(u.machine,
"sun4u") == 0 || strcmp(u.machine,
"sparc64") == 0)
605 return QStringLiteral(
"sparcv9");
606 if (strcmp(u.machine,
"sparc32") == 0)
607 return QStringLiteral(
"sparc");
609# if defined(Q_PROCESSOR_X86) || defined(QT_BUILD_INTERNAL)
611 if (strlen(u.machine) == 4 && u.machine[0] ==
'i'
612 && u.machine[2] ==
'8' && u.machine[3] ==
'6')
613 return QStringLiteral(
"i386");
614 if (strcmp(u.machine,
"amd64") == 0)
615 return QStringLiteral(
"x86_64");
617 return QString::fromLatin1(u.machine);
620 return buildCpuArchitecture();
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
652
653
654
655
656
657QString QSysInfo::buildAbi()
668 return QStringLiteral(
"unknown");
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694QString QSysInfo::kernelType()
697 return QStringLiteral(
"winnt");
698#elif defined(Q_OS_UNIX)
701 return QString::fromLatin1(u.sysname).toLower();
703 return unknownText();
707
708
709
710
711
712
713
714
715
716
717
718
719
720QString QSysInfo::kernelVersion()
723 const auto osver = QOperatingSystemVersion::current();
724 return QString::asprintf(
"%d.%d.%d",
725 osver.majorVersion(), osver.minorVersion(), osver.microVersion());
728 if (uname(&u) == 0) {
731 auto versionStr = QByteArrayView(u.kernelversion);
732 if (
auto lastSpace = versionStr.lastIndexOf(
' '); lastSpace != -1) {
733 return QString::fromLatin1(versionStr.sliced(lastSpace + 1));
736 return QString::fromLatin1(u.release);
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
776
777
778
779
780
781QString QSysInfo::productType()
785 return QStringLiteral(
"windows");
787#elif defined(Q_OS_QNX)
788 return QStringLiteral(
"qnx");
790#elif defined(Q_OS_ANDROID)
791 return QStringLiteral(
"android");
793#elif defined(Q_OS_IOS)
794 return QStringLiteral(
"ios");
795#elif defined(Q_OS_TVOS)
796 return QStringLiteral(
"tvos");
797#elif defined(Q_OS_WATCHOS)
798 return QStringLiteral(
"watchos");
799#elif defined(Q_OS_VISIONOS)
800 return QStringLiteral(
"visionos");
801#elif defined(Q_OS_MACOS)
802 return QStringLiteral(
"macos");
803#elif defined(Q_OS_DARWIN)
804 return QStringLiteral(
"darwin");
805#elif defined(Q_OS_WASM)
806 return QStringLiteral(
"wasm");
807#elif defined(Q_OS_VXWORKS)
808 return QStringLiteral(
"vxworks");
810#elif defined(USE_ETC_OS_RELEASE)
811 QUnixOSVersion unixOsVersion;
812 findUnixOsVersion(unixOsVersion);
813 if (!unixOsVersion.productType.isEmpty())
814 return unixOsVersion.productType;
816 return unknownText();
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
851
852
853
854QString QSysInfo::productVersion()
856#if defined(Q_OS_ANDROID)
857 const auto version = QOperatingSystemVersion::current();
858 return QString::asprintf(
"%d.%d", version.majorVersion(), version.minorVersion());
859#elif defined(Q_OS_DARWIN)
860 const auto version = QOperatingSystemVersion::current();
861 return QString::asprintf(
"%d.%d.%d", version.majorVersion(),
862 version.minorVersion(),
863 version.microVersion());
864#elif defined(Q_OS_WIN)
865 const char *version = osVer_helper();
867 const QLatin1Char spaceChar(
' ');
868 return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
872#elif defined(Q_OS_VXWORKS)
875 return QString::fromLatin1(u.releaseversion);
878#elif defined(USE_ETC_OS_RELEASE)
879 QUnixOSVersion unixOsVersion;
880 findUnixOsVersion(unixOsVersion);
881 if (!unixOsVersion.productVersion.isEmpty())
882 return unixOsVersion.productVersion;
886 return unknownText();
890
891
892
893
894
895
896
897
898
899
900
901
902
903QString QSysInfo::prettyProductName()
905#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
906 const auto version = QOperatingSystemVersion::current();
907 QString versionString;
908# if defined(Q_OS_DARWIN)
909 if (
const int microVersion = version.microVersion(); microVersion > 0)
910 versionString = QString::asprintf(
"%d.%d.%d", version.majorVersion(),
911 version.minorVersion(),
915 versionString = QString::asprintf(
"%d.%d", version.majorVersion(),
916 version.minorVersion());
917 QString result = version.name() + u' ';
918 const char *name = osVer_helper(version);
920 return result + versionString;
921 result += QLatin1StringView(name);
922# if !defined(Q_OS_WIN)
923 return result +
" ("_L1 + versionString + u')';
926 const auto displayVersion = windowsDisplayVersion();
927 if (!displayVersion.isEmpty())
928 result +=
" Version "_L1 + displayVersion;
931#elif defined(Q_OS_HAIKU)
932 return "Haiku "_L1 + productVersion();
933#elif defined(Q_OS_UNIX)
934# ifdef USE_ETC_OS_RELEASE
935 QUnixOSVersion unixOsVersion;
936 findUnixOsVersion(unixOsVersion);
937 if (!unixOsVersion.prettyName.isEmpty())
938 return unixOsVersion.prettyName;
942 return QString::fromLatin1(u.sysname) + u' ' + QString::fromLatin1(u.release);
944 return unknownText();
947#ifndef QT_BOOTSTRAPPED
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963QString QSysInfo::machineHostName()
966#if defined(Q_OS_LINUX)
971 return QString::fromLocal8Bit(u.nodename);
978 hostName.resize(512);
979 unsigned long len = hostName.size();
980 BOOL res = GetComputerNameEx(ComputerNameDnsHostname,
981 reinterpret_cast<
wchar_t *>(hostName.data()), &len);
982 if (!res && len > 512) {
983 hostName.resize(len - 1);
984 GetComputerNameEx(ComputerNameDnsHostname,
reinterpret_cast<
wchar_t *>(hostName.data()),
987 hostName.truncate(len);
992 if (gethostname(hostName,
sizeof(hostName)) == -1)
994 hostName[
sizeof(hostName) - 1] =
'\0';
995 return QString::fromLocal8Bit(hostName);
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027QByteArray QSysInfo::machineUniqueId()
1029#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
1030 char uuid[UuidStringLen + 1];
1031 io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching(
"IOPlatformExpertDevice"));
1032 QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
1033 CFStringGetCString(stringRef, uuid,
sizeof(uuid), kCFStringEncodingMacRoman);
1034 return QByteArray(uuid);
1035#elif defined(Q_OS_BSD4) && defined(KERN_HOSTUUID)
1036 char uuid[UuidStringLen + 1];
1037 size_t uuidlen =
sizeof(uuid);
1038 int name[] = { CTL_KERN, KERN_HOSTUUID };
1039 if (sysctl(name,
sizeof name /
sizeof name[0], &uuid, &uuidlen,
nullptr, 0) == 0
1040 && uuidlen ==
sizeof(uuid))
1041 return QByteArray(uuid, uuidlen - 1);
1042#elif defined(Q_OS_UNIX)
1046 static const char fullfilename[] =
"/usr/local/var/lib/dbus/machine-id";
1047 const char *firstfilename = fullfilename +
sizeof(
"/usr/local") - 1;
1048 int fd = qt_safe_open(firstfilename, O_RDONLY);
1049 if (fd == -1 && errno == ENOENT)
1050 fd = qt_safe_open(fullfilename, O_RDONLY);
1054 qint64 len = qt_safe_read(fd, buffer,
sizeof(buffer));
1058 return QByteArray(buffer, len);
1060#elif defined(Q_OS_WIN)
1062 const QString machineGuid = QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Cryptography)")
1063 .stringValue(L"MachineGuid");
1064 if (!machineGuid.isEmpty())
1065 return machineGuid.toLatin1();
1067 return QByteArray();
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083QByteArray QSysInfo::bootUniqueId()
1087 int fd = qt_safe_open(
"/proc/sys/kernel/random/boot_id", O_RDONLY);
1089 char uuid[UuidStringLen];
1090 qint64 len = qt_safe_read(fd, uuid,
sizeof(uuid));
1092 if (len == UuidStringLen)
1093 return QByteArray(uuid, UuidStringLen);
1095#elif defined(Q_OS_DARWIN)
1097 char uuid[UuidStringLen + 1];
1098 size_t uuidlen =
sizeof(uuid);
1099 if (sysctlbyname(
"kern.bootsessionuuid", uuid, &uuidlen,
nullptr, 0) == 0
1100 && uuidlen ==
sizeof(uuid))
1101 return QByteArray(uuid, uuidlen - 1);
1103 return QByteArray();
Combined button and popup list for selecting options.
static QString unknownText()