diff options
author | Joseph W. Joshua <joejoshw@gmail.com> | 2014-06-14 22:27:57 +0300 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2014-06-14 12:50:35 -0700 |
commit | 1ec5e6ffc4f9f32a6d7149e52b161aeaba6adfa4 (patch) | |
tree | 58a6be26495b540d3471682a1a91369bfbd9a14e | |
parent | cdd3b3d9cd5439cd56fb752e56a72045bed55f90 (diff) | |
download | subsurface-1ec5e6ffc4f9f32a6d7149e52b161aeaba6adfa4.tar.gz |
OS Detection
Implements automatic OS and architecture detection. This code has
been taken from the Qt repositories for Qt 5.4 (LGPL) and slightly
modified into the SubsurfaceSysInfo class.
Signed-off-by: Joseph W. Joshua <joejoshw@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | qt-ui/usersurvey.cpp | 4 | ||||
-rw-r--r-- | subsurface.pro | 6 | ||||
-rw-r--r-- | subsurfacesysinfo.cpp | 603 | ||||
-rw-r--r-- | subsurfacesysinfo.h | 293 |
4 files changed, 903 insertions, 3 deletions
diff --git a/qt-ui/usersurvey.cpp b/qt-ui/usersurvey.cpp index 7da7b3cdb..d9cee8ce8 100644 --- a/qt-ui/usersurvey.cpp +++ b/qt-ui/usersurvey.cpp @@ -8,12 +8,14 @@ #include "ssrf-version.h" #include "helpers.h" - +#include "subsurfacesysinfo.h" UserSurvey::UserSurvey(QWidget *parent) : QDialog(parent), ui(new Ui::UserSurvey) { ui->setupUi(this); // fill in the system data + ui->system->append(tr("Operating System: %1").arg(SubsurfaceSysInfo::prettyOsName())); + ui->system->append(tr("CPU Architecture: %1").arg(SubsurfaceSysInfo::cpuArchitecture())); } UserSurvey::~UserSurvey() diff --git a/subsurface.pro b/subsurface.pro index 8245f75d4..1172020c5 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -82,7 +82,8 @@ HEADERS = \ qt-ui/profile/ruleritem.h \ qt-ui/updatemanager.h \ qt-ui/divelogexportdialog.h \ - qt-ui/usersurvey.h + qt-ui/usersurvey.h \ + subsurfacesysinfo.h android: HEADERS -= \ qt-ui/usermanual.h \ @@ -160,7 +161,8 @@ SOURCES = \ qt-ui/profile/ruleritem.cpp \ qt-ui/updatemanager.cpp \ qt-ui/divelogexportdialog.cpp \ - qt-ui/usersurvey.cpp + qt-ui/usersurvey.cpp \ + subsurfacesysinfo.cpp android: SOURCES += android.cpp else: linux*: SOURCES += linux.c diff --git a/subsurfacesysinfo.cpp b/subsurfacesysinfo.cpp new file mode 100644 index 000000000..5d556c6fc --- /dev/null +++ b/subsurfacesysinfo.cpp @@ -0,0 +1,603 @@ +#include "subsurfacesysinfo.h" +#include <QString> +#include "qplatformdefs.h" + +#ifdef Q_OS_UNIX +#include <sys/utsname.h> +#endif + +// main part: processor type +#if defined(Q_PROCESSOR_ALPHA) +# define ARCH_PROCESSOR "alpha" +#elif defined(Q_PROCESSOR_ARM) +# define ARCH_PROCESSOR "arm" +#elif defined(Q_PROCESSOR_AVR32) +# define ARCH_PROCESSOR "avr32" +#elif defined(Q_PROCESSOR_BLACKFIN) +# define ARCH_PROCESSOR "bfin" +#elif defined(Q_PROCESSOR_X86_32) +# define ARCH_PROCESSOR "i386" +#elif defined(Q_PROCESSOR_X86_64) +# define ARCH_PROCESSOR "x86_64" +#elif defined(Q_PROCESSOR_IA64) +# define ARCH_PROCESSOR "ia64" +#elif defined(Q_PROCESSOR_MIPS) +# define ARCH_PROCESSOR "mips" +#elif defined(Q_PROCESSOR_POWER) +# define ARCH_PROCESSOR "power" +#elif defined(Q_PROCESSOR_S390) +# define ARCH_PROCESSOR "s390" +#elif defined(Q_PROCESSOR_SH) +# define ARCH_PROCESSOR "sh" +#elif defined(Q_PROCESSOR_SPARC) +# define ARCH_PROCESSOR "sparc" +#else +# define ARCH_PROCESSOR "unknown" +#endif + +// endinanness +#if defined(Q_LITTLE_ENDIAN) +# define ARCH_ENDIANNESS "little_endian" +#elif defined(Q_BIG_ENDIAN) +# define ARCH_ENDIANNESS "big_endian" +#endif + +// pointer type +#if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64)) +# define ARCH_POINTER "llp64" +#elif defined(__LP64__) || QT_POINTER_SIZE - 0 == 8 +# define ARCH_POINTER "lp64" +#else +# define ARCH_POINTER "ilp32" +#endif + +// secondary: ABI string (includes the dash) +#if defined(__ARM_EABI__) || defined(__mips_eabi) +# define ARCH_ABI1 "-eabi" +#elif defined(_MIPS_SIM) +# if _MIPS_SIM == _ABIO32 +# define ARCH_ABI1 "-o32" +# elif _MIPS_SIM == _ABIN32 +# define ARCH_ABI1 "-n32" +# elif _MIPS_SIM == _ABI64 +# define ARCH_ABI1 "-n64" +# elif _MIPS_SIM == _ABIO64 +# define ARCH_ABI1 "-o64" +# endif +#else +# define ARCH_ABI1 "" +#endif +#if defined(__ARM_PCS_VFP) || defined(__mips_hard_float) +# define ARCH_ABI2 "-hardfloat" +#else +# define ARCH_ABI2 "" +#endif + +#define ARCH_ABI ARCH_ABI1 ARCH_ABI2 + +#define ARCH_FULL ARCH_PROCESSOR "-" ARCH_ENDIANNESS "-" ARCH_POINTER ARCH_ABI + + +#if defined(Q_OS_OSX) + +Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) +{ + return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0); +} + +Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1) +{ + Q_UNUSED(encoding); + Q_UNUSED(len); + CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding()); +} + +Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { + return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); +} + +SubsurfaceSysInfo::MacVersion SubsurfaceSysInfo::macVersion() +{ +#if defined(Q_OS_OSX) + SInt32 gestalt_version; + if (Gestalt(gestaltSystemVersionMinor, &gestalt_version) == noErr) { + // add 2 because OS X 10.0 is 0x02 in the enum + return SubsurfaceSysInfo::MacVersion(gestalt_version + 2); + } +#elif defined(Q_OS_IOS) + return qt_ios_version(); // qtcore_mac_objc.mm +#endif + return SubsurfaceSysInfo::MV_Unknown; +} +const SubsurfaceSysInfo::MacVersion SubsurfaceSysInfo::MacintoshVersion = SubsurfaceSysInfo::macVersion(); +#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) + +QT_BEGIN_INCLUDE_NAMESPACE +#include "qt_windows.h" +QT_END_INCLUDE_NAMESPACE + +#ifndef Q_OS_WINRT +static inline OSVERSIONINFO winOsVersion() +{ + OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}}; + // GetVersionEx() has been deprecated in Windows 8.1 and will return + // only Windows 8 from that version on. +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# pragma warning( push ) +# pragma warning( disable : 4996 ) +# endif + GetVersionEx(&result); +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# pragma warning( pop ) +# endif +# ifndef Q_OS_WINCE + if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) { + // This could be Windows 8.1 or higher. Note that as of Windows 9, + // the major version needs to be checked as well. + DWORDLONG conditionMask = 0; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); + OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result.dwMajorVersion, result.dwMinorVersion, + result.dwBuildNumber, result.dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 }; + for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion) + result.dwMinorVersion = checkVersion.dwMinorVersion; + } +# endif // !Q_OS_WINCE + return result; +} +#endif // !Q_OS_WINRT + +SubsurfaceSysInfo::WinVersion SubsurfaceSysInfo::windowsVersion() +{ +#ifndef VER_PLATFORM_WIN32s +#define VER_PLATFORM_WIN32s 0 +#endif +#ifndef VER_PLATFORM_WIN32_WINDOWS +#define VER_PLATFORM_WIN32_WINDOWS 1 +#endif +#ifndef VER_PLATFORM_WIN32_NT +#define VER_PLATFORM_WIN32_NT 2 +#endif +#ifndef VER_PLATFORM_WIN32_CE +#define VER_PLATFORM_WIN32_CE 3 +#endif + + static SubsurfaceSysInfo::WinVersion winver; + if (winver) + return winver; +#ifdef Q_OS_WINRT + winver = SubsurfaceSysInfo::WV_WINDOWS8; +#else + winver = SubsurfaceSysInfo::WV_NT; + const OSVERSIONINFO osver = winOsVersion(); +#ifdef Q_OS_WINCE + DWORD qt_cever = 0; + qt_cever = osver.dwMajorVersion * 100; + qt_cever += osver.dwMinorVersion * 10; +#endif + switch (osver.dwPlatformId) { + case VER_PLATFORM_WIN32s: + winver = SubsurfaceSysInfo::WV_32s; + break; + case VER_PLATFORM_WIN32_WINDOWS: + // We treat Windows Me (minor 90) the same as Windows 98 + if (osver.dwMinorVersion == 90) + winver = SubsurfaceSysInfo::WV_Me; + else if (osver.dwMinorVersion == 10) + winver = SubsurfaceSysInfo::WV_98; + else + winver = SubsurfaceSysInfo::WV_95; + break; +#ifdef Q_OS_WINCE + case VER_PLATFORM_WIN32_CE: + if (qt_cever >= 600) + winver = SubsurfaceSysInfo::WV_CE_6; + if (qt_cever >= 500) + winver = SubsurfaceSysInfo::WV_CE_5; + else if (qt_cever >= 400) + winver = SubsurfaceSysInfo::WV_CENET; + else + winver = SubsurfaceSysInfo::WV_CE; + break; +#endif + default: // VER_PLATFORM_WIN32_NT + if (osver.dwMajorVersion < 5) { + winver = SubsurfaceSysInfo::WV_NT; + } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0) { + winver = SubsurfaceSysInfo::WV_2000; + } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1) { + winver = SubsurfaceSysInfo::WV_XP; + } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2) { + winver = SubsurfaceSysInfo::WV_2003; + } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0) { + winver = SubsurfaceSysInfo::WV_VISTA; + } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1) { + winver = SubsurfaceSysInfo::WV_WINDOWS7; + } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) { + winver = SubsurfaceSysInfo::WV_WINDOWS8; + } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) { + winver = SubsurfaceSysInfo::WV_WINDOWS8_1; + } else { + qWarning("Qt: Untested Windows version %d.%d detected!", + int(osver.dwMajorVersion), int(osver.dwMinorVersion)); + winver = SubsurfaceSysInfo::WV_NT_based; + } + } + +#ifdef QT_DEBUG + { + QByteArray override = qgetenv("QT_WINVER_OVERRIDE"); + if (override.isEmpty()) + return winver; + + if (override == "Me") + winver = SubsurfaceSysInfo::WV_Me; + if (override == "95") + winver = SubsurfaceSysInfo::WV_95; + else if (override == "98") + winver = SubsurfaceSysInfo::WV_98; + else if (override == "NT") + winver = SubsurfaceSysInfo::WV_NT; + else if (override == "2000") + winver = SubsurfaceSysInfo::WV_2000; + else if (override == "2003") + winver = SubsurfaceSysInfo::WV_2003; + else if (override == "XP") + winver = SubsurfaceSysInfo::WV_XP; + else if (override == "VISTA") + winver = SubsurfaceSysInfo::WV_VISTA; + else if (override == "WINDOWS7") + winver = SubsurfaceSysInfo::WV_WINDOWS7; + else if (override == "WINDOWS8") + winver = SubsurfaceSysInfo::WV_WINDOWS8; + else if (override == "WINDOWS8_1") + winver = SubsurfaceSysInfo::WV_WINDOWS8_1; + } +#endif +#endif // !Q_OS_WINRT + + return winver; +} + +static const char *winVer_helper() +{ + switch (int(SubsurfaceSysInfo::WindowsVersion)) { + case SubsurfaceSysInfo::WV_NT: + return "NT"; + case SubsurfaceSysInfo::WV_2000: + return "2000"; + case SubsurfaceSysInfo::WV_XP: + return "XP"; + case SubsurfaceSysInfo::WV_2003: + return "2003"; + case SubsurfaceSysInfo::WV_VISTA: + return "Vista"; + case SubsurfaceSysInfo::WV_WINDOWS7: + return "7"; + case SubsurfaceSysInfo::WV_WINDOWS8: + return "8"; + case SubsurfaceSysInfo::WV_WINDOWS8_1: + return "8.1"; + + case SubsurfaceSysInfo::WV_CE: + return "CE"; + case SubsurfaceSysInfo::WV_CENET: + return "CENET"; + case SubsurfaceSysInfo::WV_CE_5: + return "CE5"; + case SubsurfaceSysInfo::WV_CE_6: + return "CE6"; + } + // unknown, future version + return 0; +} + +const SubsurfaceSysInfo::WinVersion SubsurfaceSysInfo::WindowsVersion = SubsurfaceSysInfo::windowsVersion(); + +#endif + +#if defined(Q_OS_UNIX) +# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) +# define USE_ETC_OS_RELEASE +# endif +struct QUnixOSVersion +{ + // from uname(2) + QString sysName; + QString sysNameLower; + QString sysRelease; + +# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC) + // from /etc/os-release or guessed + QString versionIdentifier; // ${ID}_$VERSION_ID + QString versionText; // $PRETTY_NAME +# endif +}; + + +#ifdef USE_ETC_OS_RELEASE +static QString unquote(const char *begin, const char *end) +{ + if (*begin == '"') { + Q_ASSERT(end[-1] == '"'); + return QString::fromLatin1(begin + 1, end - begin - 2); + } + return QString::fromLatin1(begin, end - begin); +} + + +static bool readEtcOsRelease(QUnixOSVersion &v) +{ + // we're avoiding QFile here + + int fd = QT_OPEN("/etc/os-release", O_RDONLY); + if (fd == -1) + return false; + + QT_STATBUF sbuf; + if (QT_FSTAT(fd, &sbuf) == -1) { + QT_CLOSE(fd); + return false; + } + + QString partialIdentifier; + QByteArray buffer(sbuf.st_size, Qt::Uninitialized); + buffer.resize(QT_READ(fd, buffer.data(), sbuf.st_size)); + QT_CLOSE(fd); + + const char *ptr = buffer.constData(); + const char *end = buffer.constEnd(); + const char *eol; + for ( ; ptr != end; ptr = eol + 1) { + static const char idString[] = "ID="; + static const char prettyNameString[] = "PRETTY_NAME="; + static const char versionIdString[] = "VERSION_ID="; + + // find the end of the line after ptr + eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr)); + if (!eol) + eol = end - 1; + + int cmp = strncmp(ptr, idString, strlen(idString)); + if (cmp < 0) + continue; + if (cmp == 0) { + ptr += strlen(idString); + QString id = unquote(ptr, eol); + if (partialIdentifier.isNull()) + partialIdentifier = id; + else + v.versionIdentifier = id + QLatin1Char('_') + partialIdentifier; + continue; + } + + cmp = strncmp(ptr, prettyNameString, strlen(prettyNameString)); + if (cmp < 0) + continue; + if (cmp == 0) { + ptr += strlen(prettyNameString); + v.versionText = unquote(ptr, eol); + continue; + } + + cmp = strncmp(ptr, versionIdString, strlen(versionIdString)); + if (cmp < 0) + continue; + if (cmp == 0) { + ptr += strlen(versionIdString); + QString id = unquote(ptr, eol); + if (partialIdentifier.isNull()) + partialIdentifier = id; + else + v.versionIdentifier = partialIdentifier + QLatin1Char('_') + id; + continue; + } + } + + return true; +} +#endif // USE_ETC_OS_RELEASE + +static QUnixOSVersion detectUnixVersion() +{ + QUnixOSVersion v; + struct utsname u; + if (uname(&u) != -1) { + v.sysName = QString::fromLatin1(u.sysname); + v.sysNameLower = v.sysName.toLower(); + v.sysRelease = QString::fromLatin1(u.release); + } else { + v.sysName = QLatin1String("Detection failed"); + // leave sysNameLower & sysRelease unset + } + +# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC) +# ifdef USE_ETC_OS_RELEASE + if (readEtcOsRelease(v)) + return v; +# endif + + if (!v.sysNameLower.isEmpty()) { + // will produce "qnx_6.5" or "sunos_5.9" + v.versionIdentifier = v.sysNameLower + QLatin1Char('_') + v.sysRelease; + } +# endif + + return v; +} +#endif + +QString SubsurfaceSysInfo::unknownText() +{ + return QStringLiteral("unknown"); +} + +QString SubsurfaceSysInfo::cpuArchitecture() +{ + return QStringLiteral(ARCH_PROCESSOR); +} + +QString SubsurfaceSysInfo::fullCpuArchitecture() +{ + return QLatin1String(ARCH_FULL); +} + +QString SubsurfaceSysInfo::osType() +{ +#if defined(Q_OS_WINPHONE) + return QStringLiteral("winphone"); +#elif defined(Q_OS_WINRT) + return QStringLiteral("winrt"); +#elif defined(Q_OS_WINCE) + return QStringLiteral("wince"); +#elif defined(Q_OS_WIN) + return QStringLiteral("windows"); + +#elif defined(Q_OS_BLACKBERRY) + return QStringLiteral("blackberry"); +#elif defined(Q_OS_QNX) + return QStringLiteral("qnx"); + +#elif defined(Q_OS_ANDROID) + return QStringLiteral("android"); +#elif defined(Q_OS_LINUX) + return QStringLiteral("linux"); + +#elif defined(Q_OS_IOS) + return QStringLiteral("ios"); +#elif defined(Q_OS_OSX) + return QStringLiteral("osx"); +#elif defined(Q_OS_DARWIN) + return QStringLiteral("darwin"); + +#elif defined(Q_OS_FREEBSD_KERNEL) + return QStringLiteral("freebsd"); +#elif defined(Q_OS_UNIX) + QUnixOSVersion unixOsVersion = detectUnixVersion(); + if (!unixOsVersion.sysNameLower.isEmpty()) + return unixOsVersion.sysNameLower; +#endif + return unknownText(); +} + +QString SubsurfaceSysInfo::osKernelVersion() +{ +#ifdef Q_OS_WINRT + // TBD + return QString(); +#elif defined(Q_OS_WIN) + const OSVERSIONINFO osver = winOsVersion(); + return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion)) + + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber)); +#else + return detectUnixVersion().sysRelease; +#endif +} + +QString SubsurfaceSysInfo::osVersion() +{ +#if defined(Q_OS_IOS) + int major = (int(MacintoshVersion) >> 4) & 0xf; + int minor = int(MacintoshVersion) & 0xf; + if (Q_LIKELY(major < 10 && minor < 10)) { + char buf[4] = { char(major + '0'), '.', char(minor + '0'), '\0' }; + return QString::fromLatin1(buf, 3); + } + return QString::number(major) + QLatin1Char('.') + QString::number(minor); +#elif defined(Q_OS_OSX) + int minor = int(MacintoshVersion) - 2; // we're not running on Mac OS 9 + Q_ASSERT(minor < 100); + char buf[] = "10.0\0"; + if (Q_LIKELY(minor < 10)) { + buf[3] += minor; + } else { + buf[3] += minor / 10; + buf[4] = '0' + minor % 10; + } + return QString::fromLatin1(buf); +#elif defined(Q_OS_WIN) + const char *version = winVer_helper(); + if (version) + return QString::fromLatin1(version).toLower(); + // fall through + + // Android and Blackberry should not fall through to the Unix code +#elif defined(Q_OS_ANDROID) + // TBD +#elif defined(Q_OS_BLACKBERRY) + deviceinfo_details_t *deviceInfo; + if (deviceinfo_get_details(&deviceInfo) == BPS_SUCCESS) { + QString bbVersion = QString::fromLatin1(deviceinfo_details_get_device_os_version(deviceInfo)); + deviceinfo_free_details(&deviceInfo); + return bbVersion; + } +#elif defined(Q_OS_UNIX) + QUnixOSVersion unixOsVersion = detectUnixVersion(); + if (!unixOsVersion.versionIdentifier.isEmpty()) + return unixOsVersion.versionIdentifier; +#endif + + // fallback + return unknownText(); +} + +QString SubsurfaceSysInfo::prettyOsName() +{ +#if defined(Q_OS_IOS) + return QLatin1String("iOS ") + osVersion(); +#elif defined(Q_OS_OSX) + // get the known codenames + const char *basename = 0; + switch (int(MacintoshVersion)) { + case MV_CHEETAH: + case MV_PUMA: + case MV_JAGUAR: + case MV_PANTHER: + case MV_TIGER: + // This version of Qt does not run on those versions of OS X + // so this case label will never be reached + Q_UNREACHABLE(); + break; + case MV_LEOPARD: + basename = "Mac OS X Leopard ("; + break; + case MV_SNOWLEOPARD: + basename = "Mac OS X Snow Leopard ("; + break; + case MV_LION: + basename = "Mac OS X Lion ("; + break; + case MV_MOUNTAINLION: + basename = "OS X Mountain Lion ("; + break; + case MV_MAVERICKS: + basename = "OS X Mavericks ("; + break; + case MV_YOSEMITE: + basename = "OS X Yosemite ("; + break; + } + if (basename) + return QLatin1String(basename) + osVersion() + QLatin1Char(')'); + + // a future version of OS X + return QLatin1String("OS X ") + osVersion(); +#elif defined(Q_OS_WINPHONE) + return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper()); +#elif defined(Q_OS_WIN) + return QLatin1String("Windows ") + QLatin1String(winVer_helper()); +#elif defined(Q_OS_ANDROID) + return QLatin1String("Android ") + osVersion(); +#elif defined(Q_OS_BLACKBERRY) + return QLatin1String("BlackBerry ") + osVersion(); +#elif defined(Q_OS_UNIX) + QUnixOSVersion unixOsVersion = detectUnixVersion(); + if (unixOsVersion.versionText.isEmpty()) + return unixOsVersion.sysName; + else + return unixOsVersion.sysName + QLatin1String(" (") + unixOsVersion.versionText + QLatin1Char(')'); +#else + return unknownText(); +#endif +} diff --git a/subsurfacesysinfo.h b/subsurfacesysinfo.h new file mode 100644 index 000000000..8018ddb31 --- /dev/null +++ b/subsurfacesysinfo.h @@ -0,0 +1,293 @@ +#ifndef SUBSURFACESYSINFO_H +#define SUBSURFACESYSINFO_H + +#include <QtGlobal> + +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__arm64__) +# define Q_PROCESSOR_ARM +# if defined(__arm64__) +# define Q_PROCESSOR_ARM_64 +# else +# define Q_PROCESSOR_ARM_32 +# endif +# if defined(__ARM64_ARCH_8__) +# define Q_PROCESSOR_ARM_V8 +# define Q_PROCESSOR_ARM_V7 +# define Q_PROCESSOR_ARM_V6 +# define Q_PROCESSOR_ARM_V5 +# elif defined(__ARM_ARCH_7__) \ + || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7S__) \ + || defined(_ARM_ARCH_7) \ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) \ + || (defined(_M_ARM) && _M_ARM-0 >= 7) +# define Q_PROCESSOR_ARM_V7 +# define Q_PROCESSOR_ARM_V6 +# define Q_PROCESSOR_ARM_V5 +# elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) \ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) \ + || (defined(_M_ARM) && _M_ARM-0 >= 6) +# define Q_PROCESSOR_ARM_V6 +# define Q_PROCESSOR_ARM_V5 +# elif defined(__ARM_ARCH_5TEJ__) \ + || defined(__ARM_ARCH_5TE__) \ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) \ + || (defined(_M_ARM) && _M_ARM-0 >= 5) +# define Q_PROCESSOR_ARM_V5 +# endif +# if defined(__ARMEL__) +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# elif defined(__ARMEB__) +# define Q_BYTE_ORDER Q_BIG_ENDIAN +# else +// Q_BYTE_ORDER not defined, use endianness auto-detection +#endif + + +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define Q_PROCESSOR_X86_32 +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN + +# if defined(_M_IX86) +# define Q_PROCESSOR_X86 (_M_IX86/100) +# elif defined(__i686__) || defined(__athlon__) || defined(__SSE__) +# define Q_PROCESSOR_X86 6 +# elif defined(__i586__) || defined(__k6__) +# define Q_PROCESSOR_X86 5 +# elif defined(__i486__) +# define Q_PROCESSOR_X86 4 +# else +# define Q_PROCESSOR_X86 3 +#endif + +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) +# define Q_PROCESSOR_X86 6 +# define Q_PROCESSOR_X86_64 +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# define Q_PROCESSOR_WORDSIZE 8 + +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) +# define Q_PROCESSOR_IA64 +# define Q_PROCESSOR_WORDSIZE 8 + +#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000) +# define Q_PROCESSOR_MIPS +# if defined(_MIPS_ARCH_MIPS1) || (defined(__mips) && __mips - 0 >= 1) +# define Q_PROCESSOR_MIPS_I +# endif +# if defined(_MIPS_ARCH_MIPS2) || (defined(__mips) && __mips - 0 >= 2) +# define Q_PROCESSOR_MIPS_II +# endif +# if defined(_MIPS_ARCH_MIPS32) || defined(__mips32) +# define Q_PROCESSOR_MIPS_32 +# endif +# if defined(_MIPS_ARCH_MIPS3) || (defined(__mips) && __mips - 0 >= 3) +# define Q_PROCESSOR_MIPS_III +# endif +# if defined(_MIPS_ARCH_MIPS4) || (defined(__mips) && __mips - 0 >= 4) +# define Q_PROCESSOR_MIPS_IV +# endif +# if defined(_MIPS_ARCH_MIPS5) || (defined(__mips) && __mips - 0 >= 5) +# define Q_PROCESSOR_MIPS_V +# endif +# if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) +# define Q_PROCESSOR_MIPS_64 +# endif +# if defined(__MIPSEL__) +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# elif defined(__MIPSEB__) +# define Q_BYTE_ORDER Q_BIG_ENDIAN +# else +// Q_BYTE_ORDER not defined, use endianness auto-detection +#endif + + +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \ + || defined(_M_MPPC) || defined(_M_PPC) +# define Q_PROCESSOR_POWER +# if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) +# define Q_PROCESSOR_POWER_64 +# else +# define Q_PROCESSOR_POWER_32 +# endif + +#elif defined(__s390__) +# define Q_PROCESSOR_S390 +# if defined(__s390x__) +# define Q_PROCESSOR_S390_X +# endif +# define Q_BYTE_ORDER Q_BIG_ENDIAN + + +#endif + +// Some processors support either endian format, try to detect which we are using. +#if !defined(Q_BYTE_ORDER) +# if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN) +// Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults +# define Q_BYTE_ORDER __BYTE_ORDER__ +# elif defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) +# define Q_BYTE_ORDER Q_BIG_ENDIAN +# elif defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) \ + || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) // Windows CE is always little-endian according to MSDN. +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# else +# error "Unable to determine byte order!" +# endif +#endif + +#ifndef Q_PROCESSOR_WORDSIZE +# ifdef __SIZEOF_POINTER__ +/* GCC & friends define this */ +# define Q_PROCESSOR_WORDSIZE __SIZEOF_POINTER__ +# elif defined(_LP64) || defined(__LP64__) || defined(WIN64) || defined(_WIN64) +# define Q_PROCESSOR_WORDSIZE 8 +# else +# define Q_PROCESSOR_WORDSIZE QT_POINTER_SIZE +# endif +#endif + +class QString; +class SubsurfaceSysInfo { +public: + enum Sizes { + WordSize = (sizeof(void *)<<3) + }; + +#ifndef QStringLiteral + // no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t + // fallback, return a temporary QString + // source code is assumed to be encoded in UTF-8 + +# define QStringLiteral(str) QString::fromUtf8("" str "", sizeof(str) - 1) +#endif + + +#if defined(QT_BUILD_QMAKE) + enum Endian { + BigEndian, + LittleEndian + }; + /* needed to bootstrap qmake */ + static const int ByteOrder; +#elif defined(Q_BYTE_ORDER) + enum Endian { + BigEndian, + LittleEndian + +# ifdef Q_QDOC + , ByteOrder = <platform-dependent> +# elif Q_BYTE_ORDER == Q_BIG_ENDIAN + , ByteOrder = BigEndian +# elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN + , ByteOrder = LittleEndian +# else +# error "Undefined byte order" +# endif + }; +#endif +#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) + enum WinVersion { + WV_32s = 0x0001, + WV_95 = 0x0002, + WV_98 = 0x0003, + WV_Me = 0x0004, + WV_DOS_based= 0x000f, + + /* codenames */ + WV_NT = 0x0010, + WV_2000 = 0x0020, + WV_XP = 0x0030, + WV_2003 = 0x0040, + WV_VISTA = 0x0080, + WV_WINDOWS7 = 0x0090, + WV_WINDOWS8 = 0x00a0, + WV_WINDOWS8_1 = 0x00b0, + WV_NT_based = 0x00f0, + + /* version numbers */ + WV_4_0 = WV_NT, + WV_5_0 = WV_2000, + WV_5_1 = WV_XP, + WV_5_2 = WV_2003, + WV_6_0 = WV_VISTA, + WV_6_1 = WV_WINDOWS7, + WV_6_2 = WV_WINDOWS8, + WV_6_3 = WV_WINDOWS8_1, + + WV_CE = 0x0100, + WV_CENET = 0x0200, + WV_CE_5 = 0x0300, + WV_CE_6 = 0x0400, + WV_CE_based = 0x0f00 + }; + static const WinVersion WindowsVersion; + static WinVersion windowsVersion(); + +#endif +#ifdef Q_OS_MAC +# define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor) + enum MacVersion { + MV_Unknown = 0x0000, + + /* version */ + MV_9 = 0x0001, + MV_10_0 = 0x0002, + MV_10_1 = 0x0003, + MV_10_2 = 0x0004, + MV_10_3 = 0x0005, + MV_10_4 = 0x0006, + MV_10_5 = 0x0007, + MV_10_6 = 0x0008, + MV_10_7 = 0x0009, + MV_10_8 = 0x000A, + MV_10_9 = 0x000B, + MV_10_10 = 0x000C, + + /* codenames */ + MV_CHEETAH = MV_10_0, + MV_PUMA = MV_10_1, + MV_JAGUAR = MV_10_2, + MV_PANTHER = MV_10_3, + MV_TIGER = MV_10_4, + MV_LEOPARD = MV_10_5, + MV_SNOWLEOPARD = MV_10_6, + MV_LION = MV_10_7, + MV_MOUNTAINLION = MV_10_8, + MV_MAVERICKS = MV_10_9, + MV_YOSEMITE = MV_10_10, + + /* iOS */ + MV_IOS = 1 << 8, + MV_IOS_4_3 = Q_MV_IOS(4, 3), + MV_IOS_5_0 = Q_MV_IOS(5, 0), + MV_IOS_5_1 = Q_MV_IOS(5, 1), + MV_IOS_6_0 = Q_MV_IOS(6, 0), + MV_IOS_6_1 = Q_MV_IOS(6, 1), + MV_IOS_7_0 = Q_MV_IOS(7, 0), + MV_IOS_7_1 = Q_MV_IOS(7, 1), + MV_IOS_8_0 = Q_MV_IOS(8, 0) + }; + static const MacVersion MacintoshVersion; + static MacVersion macVersion(); +#endif + static QString unknownText(); + static QString cpuArchitecture(); + static QString fullCpuArchitecture(); + static QString osType(); + static QString osKernelVersion(); + static QString osVersion(); + static QString prettyOsName(); +}; + + +#endif // SUBSURFACESYSINFO_H |