AutorÃa | Ultima modificación | Ver Log |
// Copyright 2019 Google//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h"#include <mach/mach.h>#include <sys/mount.h>#include <sys/sysctl.h>#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h"#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"#import "Crashlytics/Shared/FIRCLSFABHost.h"#if TARGET_OS_IPHONE#import <UIKit/UIKit.h>#else#import <Cocoa/Cocoa.h>#endif#define CLS_HOST_SYSCTL_BUFFER_SIZE (128)#define CLS_MAX_ARM64_NATIVE_PAGE_SIZE (1024 * 16)#if CLS_CPU_ARM64#define CLS_MAX_NATIVE_PAGE_SIZE CLS_MAX_ARM64_NATIVE_PAGE_SIZE#else// return 4K, which is correct for all platforms except arm64, currently#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4)#endif#define CLS_MIN_NATIVE_PAGE_SIZE (1024 * 4)#pragma mark Prototypesstatic void FIRCLSHostWriteSysctlEntry(FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize);static void FIRCLSHostWriteModelInfo(FIRCLSFile* file);static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file);#pragma mark - APIvoid FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext) {_firclsContext.readonly->host.pageSize = FIRCLSHostGetPageSize();_firclsContext.readonly->host.documentDirectoryPath = NULL;// determine where the document directory is mounted, so we can get file system statistics laterNSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);if ([paths count]) {_firclsContext.readonly->host.documentDirectoryPath =FIRCLSDupString([[paths objectAtIndex:0] fileSystemRepresentation]);}}vm_size_t FIRCLSHostGetPageSize(void) {size_t size;int pageSize;// hw.pagesize is defined as HW_PAGESIZE, which is an int. It's important to match// these types. Turns out that sysctl will not init the data to zero, but it appears// that sysctlbyname does. This API is nicer, but that's important to keep in mind.int maxNativePageSize = CLS_MAX_NATIVE_PAGE_SIZE;// On Apple Silicon, we need to use the arm64 page size// even if we're in x86 land.if (FIRCLSHostIsRosettaTranslated()) {FIRCLSSDKLog("Running under Rosetta 2 emulation. Using the arm64 page size.\n");maxNativePageSize = CLS_MAX_ARM64_NATIVE_PAGE_SIZE;}pageSize = 0;size = sizeof(pageSize);if (sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0) != 0) {FIRCLSSDKLog("sysctlbyname failed while trying to get hw.pagesize\n");return maxNativePageSize;}// if the returned size is not the expected value, abortif (size != sizeof(pageSize)) {return maxNativePageSize;}// put in some guards to make sure our size is reasonableif (pageSize > maxNativePageSize) {return maxNativePageSize;}if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) {return CLS_MIN_NATIVE_PAGE_SIZE;}return pageSize;}// This comes from the Apple documentation here:// https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environmentbool FIRCLSHostIsRosettaTranslated() {#if TARGET_OS_MACint result = 0;size_t size = sizeof(result);if (sysctlbyname("sysctl.proc_translated", &result, &size, NULL, 0) == -1) {// If we get an error, or 0, we're going to treat this as x86_64 macOS nativeif (errno == ENOENT) {return false;}// This is the error caseFIRCLSSDKLog("sysctlbyname failed while trying to get sysctl.proc_translated for Rosetta 2 ""translation\n");return false;}return result == 1;#elsereturn false;#endif}static void FIRCLSHostWriteSysctlEntry(FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize) {if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) {FIRCLSFileWriteHashEntryString(file, key, "(failed)");return;}FIRCLSFileWriteHashEntryString(file, key, buffer);}static void FIRCLSHostWriteModelInfo(FIRCLSFile* file) {FIRCLSFileWriteHashEntryString(file, "model", [FIRCLSHostModelInfo() UTF8String]);// allocate a static buffer for the sysctl values, which are typically// quite shortchar buffer[CLS_HOST_SYSCTL_BUFFER_SIZE];#if TARGET_OS_EMBEDDEDFIRCLSHostWriteSysctlEntry(file, "machine", "hw.model", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);#elseFIRCLSHostWriteSysctlEntry(file, "machine", "hw.machine", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);FIRCLSHostWriteSysctlEntry(file, "cpu", "machdep.cpu.brand_string", buffer,CLS_HOST_SYSCTL_BUFFER_SIZE);#endif}static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file) {FIRCLSFileWriteHashEntryString(file, "os_build_version", [FIRCLSHostOSBuildVersion() UTF8String]);FIRCLSFileWriteHashEntryString(file, "os_display_version",[FIRCLSHostOSDisplayVersion() UTF8String]);FIRCLSFileWriteHashEntryString(file, "platform", [FIRCLSApplicationGetPlatform() UTF8String]);FIRCLSFileWriteHashEntryString(file, "firebase_platform",[FIRCLSApplicationGetFirebasePlatform() UTF8String]);}bool FIRCLSHostRecord(FIRCLSFile* file) {FIRCLSFileWriteSectionStart(file, "host");FIRCLSFileWriteHashStart(file);FIRCLSHostWriteModelInfo(file);FIRCLSHostWriteOSVersionInfo(file);FIRCLSFileWriteHashEntryString(file, "locale",[[[NSLocale currentLocale] localeIdentifier] UTF8String]);FIRCLSFileWriteHashEnd(file);FIRCLSFileWriteSectionEnd(file);return true;}void FIRCLSHostWriteDiskUsage(FIRCLSFile* file) {struct statfs tStats;FIRCLSFileWriteSectionStart(file, "storage");FIRCLSFileWriteHashStart(file);if (statfs(_firclsContext.readonly->host.documentDirectoryPath, &tStats) == 0) {FIRCLSFileWriteHashEntryUint64(file, "free", tStats.f_bavail * tStats.f_bsize);FIRCLSFileWriteHashEntryUint64(file, "total", tStats.f_blocks * tStats.f_bsize);}FIRCLSFileWriteHashEnd(file);FIRCLSFileWriteSectionEnd(file);}