summaryrefslogtreecommitdiff
path: root/source/base/PlatformInfo.c
diff options
context:
space:
mode:
authorpepper <peppersclothescult@gmail.com>2015-01-10 21:32:32 -0800
committerpepper <peppersclothescult@gmail.com>2015-01-10 21:32:32 -0800
commitd53fa8a169832563c62262078b8d2ffe5cab8473 (patch)
treeb911d06d357d009c976709780f10e92ce915228a /source/base/PlatformInfo.c
first
Diffstat (limited to 'source/base/PlatformInfo.c')
-rw-r--r--source/base/PlatformInfo.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/source/base/PlatformInfo.c b/source/base/PlatformInfo.c
new file mode 100644
index 0000000..44c45cc
--- /dev/null
+++ b/source/base/PlatformInfo.c
@@ -0,0 +1,272 @@
+//
+// PlatformInfo.c - MrsWatson
+// Created by Nik Reiman on 1/2/12.
+// Copyright (c) 2012 Teragon Audio. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include <stdio.h>
+#include <string.h>
+
+#include "base/PlatformInfo.h"
+#include "logging/EventLogger.h"
+
+#if LINUX
+#include <sys/utsname.h>
+#include "base/File.h"
+
+#define LSB_FILE_PATH "/etc/lsb-release"
+#define LSB_DISTRIBUTION "DISTRIB_DESCRIPTION"
+#endif
+
+static PlatformType _getPlatformType()
+{
+#if MACOSX
+ return PLATFORM_MACOSX;
+#elif WINDOWS
+ return PLATFORM_WINDOWS;
+#elif LINUX
+ return PLATFORM_LINUX;
+#else
+ return PLATFORM_UNSUPPORTED;
+#endif
+}
+
+static const char *_getShortPlatformName(void)
+{
+#if MACOSX
+ return "Mac OS X";
+#elif WINDOWS
+
+ if (platformInfoIsRuntime64Bit()) {
+ return "Windows 64-bit";
+ } else {
+ return "Windows 32-bit";
+ }
+
+#elif LINUX
+
+ if (platformInfoIsRuntime64Bit()) {
+ return "Linux-x86_64";
+ } else {
+ return "Linux-i686";
+ }
+
+#else
+ return "Unsupported";
+#endif
+}
+
+#if LINUX
+static void _findLsbDistribution(void *item, void *userData)
+{
+ CharString line = (CharString)item;
+ CharString distributionName = (CharString)userData;
+ LinkedList tokens = charStringSplit(line, '=');
+
+ if (tokens != NULL && linkedListLength(tokens) == 2) {
+ CharString *tokensArray = (CharString *)linkedListToArray(tokens);
+ CharString key = tokensArray[0];
+ CharString value = tokensArray[1];
+
+ if (!strcmp(key->data, LSB_DISTRIBUTION)) {
+ charStringCopy(distributionName, value);
+ }
+
+ free(tokensArray);
+ }
+
+ freeLinkedListAndItems(tokens, (LinkedListFreeItemFunc)freeCharString);
+}
+#endif
+
+#if MACOSX
+extern void _getMacVersionString(CharString outString);
+#endif
+
+static CharString _getPlatformName(void)
+{
+ CharString result = newCharString();
+#if MACOSX
+ charStringCopyCString(result, _getShortPlatformName());
+ _getMacVersionString(result);
+#elif LINUX
+ CharString distributionName = newCharString();
+ struct utsname systemInfo;
+ File lsbRelease = NULL;
+ LinkedList lsbReleaseLines = NULL;
+
+ if (uname(&systemInfo) != 0) {
+ logWarn("Could not get system information from uname");
+ charStringCopyCString(result, "Linux (Unknown platform)");
+ freeCharString(distributionName);
+ return result;
+ }
+
+ charStringCopyCString(distributionName, "(Unknown distribution)");
+
+ lsbRelease = newFileWithPathCString(LSB_FILE_PATH);
+
+ if (fileExists(lsbRelease)) {
+ lsbReleaseLines = fileReadLines(lsbRelease);
+
+ if (lsbReleaseLines != NULL && linkedListLength(lsbReleaseLines) > 0) {
+ linkedListForeach(lsbReleaseLines, _findLsbDistribution, distributionName);
+ }
+ }
+
+ if (charStringIsEmpty(result)) {
+ snprintf(result->data, result->capacity, "Linux %s, kernel %s %s",
+ distributionName->data, systemInfo.release, systemInfo.machine);
+ }
+
+ freeCharString(distributionName);
+ freeLinkedListAndItems(lsbReleaseLines, (LinkedListFreeItemFunc)freeCharString);
+ freeFile(lsbRelease);
+#elif WINDOWS
+ OSVERSIONINFOEX versionInformation;
+ memset(&versionInformation, 0, sizeof(OSVERSIONINFOEX));
+ versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ GetVersionEx((OSVERSIONINFO *)&versionInformation);
+ // Generic string which will also work with newer versions of windows
+ snprintf(result->data, result->capacity, "Windows %d.%d",
+ versionInformation.dwMajorVersion, versionInformation.dwMinorVersion);
+
+ // This is a bit lame, but it seems that this is the standard way of getting
+ // the platform name on Windows.
+ switch (versionInformation.dwMajorVersion) {
+ case 6:
+ switch (versionInformation.dwMinorVersion) {
+ case 2:
+ charStringCopyCString(result, "Windows 8");
+ break;
+
+ case 1:
+ charStringCopyCString(result, "Windows 7");
+ break;
+
+ case 0:
+ charStringCopyCString(result, "Windows Vista");
+ break;
+ }
+
+ break;
+
+ case 5:
+ switch (versionInformation.dwMinorVersion) {
+ case 2:
+ charStringCopyCString(result, "Windows Server 2003");
+ break;
+
+ case 1:
+ charStringCopyCString(result, "Windows XP");
+ break;
+
+ case 0:
+ charStringCopyCString(result, "Windows 2000");
+ break;
+ }
+
+ break;
+ }
+
+#else
+ charStringCopyCString(result, "Unsupported platform");
+#endif
+
+ return result;
+}
+
+boolByte platformInfoIsRuntime64Bit(void)
+{
+ return (boolByte)(sizeof(void *) == 8);
+}
+
+boolByte platformInfoIsHost64Bit(void)
+{
+ boolByte result = false;
+
+#if LINUX
+ struct utsname systemInfo;
+
+ if (uname(&systemInfo) != 0) {
+ logError("Could not get system bitness from uname");
+ } else {
+ result = (boolByte)(strcmp(systemInfo.machine, "x86_64") == 0);
+ }
+
+#elif MACOSX
+#elif WINDOWS
+ typedef BOOL (WINAPI * IsWow64ProcessFuncPtr)(HANDLE, PBOOL);
+ BOOL isProcessRunningInWow64 = false;
+ IsWow64ProcessFuncPtr isWow64ProcessFunc = NULL;
+
+ // The IsWow64Process() function is not available on all versions of Windows,
+ // so it must be looked up first and called only if it exists.
+ isWow64ProcessFunc = (IsWow64ProcessFuncPtr)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+ if (isWow64ProcessFunc != NULL) {
+ if (isWow64ProcessFunc(GetCurrentProcess(), &isProcessRunningInWow64)) {
+ // IsWow64Process will only return true if the current process is a 32-bit
+ // application running on 64-bit Windows.
+ if (isProcessRunningInWow64) {
+ result = true;
+ } else {
+ // If false, then we can assume that the host has the same bitness as
+ // the executable.
+ result = platformInfoIsRuntime64Bit();
+ }
+ }
+ }
+
+#else
+ logUnsupportedFeature("Get host 64-bitness");
+#endif
+
+ return result;
+}
+
+boolByte platformInfoIsLittleEndian(void)
+{
+ int num = 1;
+ return (boolByte)(*(char *)&num == 1);
+}
+
+PlatformInfo newPlatformInfo(void)
+{
+ PlatformInfo platformInfo = (PlatformInfo)malloc(sizeof(PlatformInfoMembers));
+ platformInfo->type = _getPlatformType();
+ platformInfo->name = _getPlatformName();
+ platformInfo->shortName = newCharStringWithCString(_getShortPlatformName());
+ platformInfo->is64Bit = platformInfoIsHost64Bit();
+ return platformInfo;
+}
+
+void freePlatformInfo(PlatformInfo self)
+{
+ if (self != NULL) {
+ freeCharString(self->name);
+ freeCharString(self->shortName);
+ free(self);
+ }
+}