@@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,31 +24,39 @@ #include "platform.h" #ifdef HAVE_SYS_UTSNAME_H # include #endif -#if defined(OF_MACOS) || defined(OF_NETBSD) +#if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD) # include #endif + +#ifdef OF_AMIGAOS +# include +# include +#endif #if defined(OF_AMIGAOS4) # include -# include #elif defined(OF_MORPHOS) # include -# include +#endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# import +# undef nx_id #endif #import "OFSystemInfo.h" #import "OFApplication.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFLocale.h" #import "OFOnce.h" #import "OFString.h" - -#import "OFNotImplementedException.h" +#import "OFURL.h" #if defined(OF_MACOS) || defined(OF_IOS) # ifdef HAVE_SYSDIR_H # include # endif @@ -212,16 +220,14 @@ objc_autoreleasePoolPop(pool); } # endif #elif defined(OF_ANDROID) /* TODO */ -#elif defined(OF_MORPHOS) - /* TODO */ -#elif defined(OF_AMIGAOS4) - /* TODO */ -#elif defined(OF_AMIGAOS_M68K) - /* TODO */ +#elif defined(OF_AMIGAOS) + operatingSystemVersion = [[OFString alloc] + initWithFormat: @"Kickstart %u.%u", + SysBase->LibNode.lib_Version, SysBase->SoftVer]; #elif defined(OF_WII) || defined(NINTENDO_3DS) || defined(OF_NINTENDO_DS) || \ defined(OF_PSP) || defined(OF_MSDOS) /* Intentionally nothing */ #elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) struct utsname utsname; @@ -232,10 +238,22 @@ operatingSystemVersion = [[OFString alloc] initWithCString: utsname.release encoding: [OFLocale encoding]]; #endif } + +#ifdef OF_NINTENDO_SWITCH +static OFURL *tmpFSURL = nil; + +static void +mountTmpFS(void) +{ + if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs"))) + tmpFSURL = [[OFURL alloc] initFileURLWithPath: @"tmpfs:/" + isDirectory: true]; +} +#endif #if defined(OF_X86_64) || defined(OF_X86) static OF_INLINE struct X86Regs OF_CONST_FUNC x86CPUID(uint32_t eax, uint32_t ecx) { @@ -318,16 +336,16 @@ + (OFString *)ObjFWVersion { return @PACKAGE_VERSION; } -+ (unsigned int)ObjFWVersionMajor ++ (unsigned short)ObjFWVersionMajor { return OBJFW_VERSION_MAJOR; } -+ (unsigned int)ObjFWVersionMinor ++ (unsigned short)ObjFWVersionMinor { return OBJFW_VERSION_MINOR; } + (OFString *)operatingSystemName @@ -344,13 +362,13 @@ OFOnce(&onceControl, initOperatingSystemVersion); return operatingSystemVersion; } -#ifdef OF_HAVE_FILES -+ (OFString *)userDataPath ++ (OFURL *)userDataURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION @@ -359,23 +377,19 @@ state = sysdir_start_search_path_enumeration( SYSDIR_DIRECTORY_APPLICATION_SUPPORT, SYSDIR_DOMAIN_MASK_USER); if (sysdir_get_next_search_path_enumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; } else { # endif NSSearchPathEnumerationState state; state = NSStartSearchPathEnumeration( NSApplicationSupportDirectory, NSUserDomainMask); if (NSGetNextSearchPathEnumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION } # endif path = [OFMutableString stringWithUTF8String: pathC]; @@ -382,67 +396,69 @@ if ([path hasPrefix: @"~"]) { OFDictionary *env = [OFApplication environment]; OFString *home; if ((home = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; [path deleteCharactersInRange: OFRangeMake(0, 1)]; [path prependString: home]; } [path makeImmutable]; - return path; + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return appData; + return [OFURL fileURLWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"PROGDIR:"; + return [OFURL fileURLWithPath: @"PROGDIR:" isDirectory: true]; # else OFDictionary *env = [OFApplication environment]; OFString *var; + OFURL *URL; void *pool; if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil && var.length > 0) - return var; + return [OFURL fileURLWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; pool = objc_autoreleasePoolPush(); - var = [[OFString pathWithComponents: [OFArray arrayWithObjects: - var, @".local", @"share", nil]] retain]; + var = [OFString pathWithComponents: [OFArray arrayWithObjects: + var, @".local", @"share", nil]]; + URL = [[OFURL alloc] initFileURLWithPath: var isDirectory: true]; objc_autoreleasePoolPop(pool); - return [var autorelease]; + return [URL autorelease]; # endif +#else + return nil; +#endif } -+ (OFString *)userConfigPath ++ (OFURL *)userConfigURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION @@ -450,23 +466,19 @@ sysdir_search_path_enumeration_state state; state = sysdir_start_search_path_enumeration( SYSDIR_DIRECTORY_LIBRARY, SYSDIR_DOMAIN_MASK_USER); if (sysdir_get_next_search_path_enumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; } else { # endif NSSearchPathEnumerationState state; state = NSStartSearchPathEnumeration(NSLibraryDirectory, NSUserDomainMask); if (NSGetNextSearchPathEnumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION } # endif path = [OFMutableString stringWithUTF8String: pathC]; @@ -473,109 +485,134 @@ if ([path hasPrefix: @"~"]) { OFDictionary *env = [OFApplication environment]; OFString *home; if ((home = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; [path deleteCharactersInRange: OFRangeMake(0, 1)]; [path prependString: home]; } [path appendString: @"/Preferences"]; [path makeImmutable]; - return path; + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return appData; + return [OFURL fileURLWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"PROGDIR:"; + return [OFURL fileURLWithPath: @"PROGDIR:" isDirectory: true]; # else OFDictionary *env = [OFApplication environment]; OFString *var; if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil && var.length > 0) - return var; + return [OFURL fileURLWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; + + var = [var stringByAppendingPathComponent: @".config"]; - return [var stringByAppendingPathComponent: @".config"]; + return [OFURL fileURLWithPath: var isDirectory: true]; # endif +#else + return nil; +#endif } -+ (OFString *)temporaryDirectoryPath ++ (OFURL *)temporaryDirectoryURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char buffer[PATH_MAX]; size_t length; + OFString *path; if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0) - return @"/tmp"; + return [OFURL fileURLWithPath: @"/tmp" isDirectory: true]; - return [OFString stringWithCString: buffer + path = [OFString stringWithCString: buffer encoding: [OFLocale encoding] length: length - 1]; + + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) + OFString *path; + if ([self isWindowsNT]) { wchar_t buffer[PATH_MAX]; if (!GetTempPathW(PATH_MAX, buffer)) return nil; - return [OFString stringWithUTF16String: buffer]; + path = [OFString stringWithUTF16String: buffer]; } else { char buffer[PATH_MAX]; if (!GetTempPathA(PATH_MAX, buffer)) return nil; - return [OFString stringWithCString: buffer + path = [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; } + + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"T:"; + return [OFURL fileURLWithPath: @"T:" isDirectory: true]; +# elif defined(OF_MSDOS) + OFString *path = [[OFApplication environment] objectForKey: @"TEMP"]; + + if (path == nil) + return nil; + + return [OFURL fileURLWithPath: path isDirectory: true]; +# elif defined(OF_MINT) + return [OFURL fileURLWithPath: @"u:\\tmp" isDirectory: true]; +# elif defined(OF_NINTENDO_SWITCH) + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, mountTmpFS); + + return tmpFSURL; # else OFString *path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; if (path != nil) - return path; + return [OFURL fileURLWithPath: path]; - return @"/tmp"; + return [OFURL fileURLWithPath: @"/tmp"]; # endif -} +#else + return nil; #endif +} + (OFString *)CPUVendor { #if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) struct X86Regs regs = x86CPUID(0, 0); @@ -589,33 +626,49 @@ buffer[2] = regs.ecx; return [OFString stringWithCString: (char *)buffer encoding: OFStringEncodingASCII length: 12]; +#elif defined(OF_M68K) + return @"Motorola"; #else return nil; #endif } + (OFString *)CPUModel { #if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) + struct X86Regs regs = x86CPUID(0x80000000, 0); uint32_t buffer[12]; size_t i; + if (regs.eax < 0x80000004) + return nil; + i = 0; for (uint32_t eax = 0x80000002; eax <= 0x80000004; eax++) { - struct X86Regs regs = x86CPUID(eax, 0); - + regs = x86CPUID(eax, 0); buffer[i++] = regs.eax; buffer[i++] = regs.ebx; buffer[i++] = regs.ecx; buffer[i++] = regs.edx; } return [OFString stringWithCString: (char *)buffer encoding: OFStringEncodingASCII]; +#elif defined(OF_MACOS) || defined(OF_IOS) + char buffer[128]; + size_t length = sizeof(buffer); + + if (sysctlbyname("machdep.cpu.brand_string", &buffer, &length, + NULL, 0) != 0) + return nil; + + return [OFString stringWithCString: buffer + encoding: [OFLocale encoding] + length: length]; #elif defined(OF_AMIGAOS4) CONST_STRPTR model, version; GetCPUInfoTags(GCIT_ModelString, &model, GCIT_VersionString, &version, TAG_END); @@ -623,10 +676,23 @@ if (version != NULL) return [OFString stringWithFormat: @"%s V%s", model, version]; else return [OFString stringWithCString: model encoding: OFStringEncodingASCII]; +#elif defined(OF_AMIGAOS_M68K) + if (SysBase->AttnFlags & AFF_68060) + return @"68060"; + if (SysBase->AttnFlags & AFF_68040) + return @"68040"; + if (SysBase->AttnFlags & AFF_68030) + return @"68030"; + if (SysBase->AttnFlags & AFF_68020) + return @"68020"; + if (SysBase->AttnFlags & AFF_68010) + return @"68010"; + else + return @"68000"; #else return nil; #endif }