Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// Copyright 2019 Google
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
 
15
#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h"
16
 
17
#include <mach/mach.h>
18
#include <sys/mount.h>
19
#include <sys/sysctl.h>
20
 
21
#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h"
22
#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h"
23
#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"
24
#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h"
25
#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"
26
#import "Crashlytics/Shared/FIRCLSFABHost.h"
27
 
28
#if TARGET_OS_IPHONE
29
#import <UIKit/UIKit.h>
30
#else
31
#import <Cocoa/Cocoa.h>
32
#endif
33
 
34
#define CLS_HOST_SYSCTL_BUFFER_SIZE (128)
35
#define CLS_MAX_ARM64_NATIVE_PAGE_SIZE (1024 * 16)
36
 
37
#if CLS_CPU_ARM64
38
#define CLS_MAX_NATIVE_PAGE_SIZE CLS_MAX_ARM64_NATIVE_PAGE_SIZE
39
#else
40
// return 4K, which is correct for all platforms except arm64, currently
41
#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4)
42
#endif
43
#define CLS_MIN_NATIVE_PAGE_SIZE (1024 * 4)
44
 
45
#pragma mark Prototypes
46
static void FIRCLSHostWriteSysctlEntry(
47
    FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize);
48
static void FIRCLSHostWriteModelInfo(FIRCLSFile* file);
49
static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file);
50
 
51
#pragma mark - API
52
void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext) {
53
  _firclsContext.readonly->host.pageSize = FIRCLSHostGetPageSize();
54
  _firclsContext.readonly->host.documentDirectoryPath = NULL;
55
 
56
  // determine where the document directory is mounted, so we can get file system statistics later
57
  NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
58
  if ([paths count]) {
59
    _firclsContext.readonly->host.documentDirectoryPath =
60
        FIRCLSDupString([[paths objectAtIndex:0] fileSystemRepresentation]);
61
  }
62
}
63
 
64
vm_size_t FIRCLSHostGetPageSize(void) {
65
  size_t size;
66
  int pageSize;
67
 
68
  // hw.pagesize is defined as HW_PAGESIZE, which is an int. It's important to match
69
  // these types. Turns out that sysctl will not init the data to zero, but it appears
70
  // that sysctlbyname does. This API is nicer, but that's important to keep in mind.
71
 
72
  int maxNativePageSize = CLS_MAX_NATIVE_PAGE_SIZE;
73
 
74
  // On Apple Silicon, we need to use the arm64 page size
75
  // even if we're in x86 land.
76
  if (FIRCLSHostIsRosettaTranslated()) {
77
    FIRCLSSDKLog("Running under Rosetta 2 emulation. Using the arm64 page size.\n");
78
 
79
    maxNativePageSize = CLS_MAX_ARM64_NATIVE_PAGE_SIZE;
80
  }
81
 
82
  pageSize = 0;
83
  size = sizeof(pageSize);
84
  if (sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0) != 0) {
85
    FIRCLSSDKLog("sysctlbyname failed while trying to get hw.pagesize\n");
86
 
87
    return maxNativePageSize;
88
  }
89
 
90
  // if the returned size is not the expected value, abort
91
  if (size != sizeof(pageSize)) {
92
    return maxNativePageSize;
93
  }
94
 
95
  // put in some guards to make sure our size is reasonable
96
  if (pageSize > maxNativePageSize) {
97
    return maxNativePageSize;
98
  }
99
 
100
  if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) {
101
    return CLS_MIN_NATIVE_PAGE_SIZE;
102
  }
103
 
104
  return pageSize;
105
}
106
 
107
// This comes from the Apple documentation here:
108
// https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment
109
bool FIRCLSHostIsRosettaTranslated() {
110
#if TARGET_OS_MAC
111
  int result = 0;
112
  size_t size = sizeof(result);
113
  if (sysctlbyname("sysctl.proc_translated", &result, &size, NULL, 0) == -1) {
114
    // If we get an error, or 0, we're going to treat this as x86_64 macOS native
115
    if (errno == ENOENT) {
116
      return false;
117
    }
118
    // This is the error case
119
    FIRCLSSDKLog("sysctlbyname failed while trying to get sysctl.proc_translated for Rosetta 2 "
120
                 "translation\n");
121
    return false;
122
  }
123
  return result == 1;
124
 
125
#else
126
  return false;
127
#endif
128
}
129
 
130
static void FIRCLSHostWriteSysctlEntry(
131
    FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize) {
132
  if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) {
133
    FIRCLSFileWriteHashEntryString(file, key, "(failed)");
134
    return;
135
  }
136
 
137
  FIRCLSFileWriteHashEntryString(file, key, buffer);
138
}
139
 
140
static void FIRCLSHostWriteModelInfo(FIRCLSFile* file) {
141
  FIRCLSFileWriteHashEntryString(file, "model", [FIRCLSHostModelInfo() UTF8String]);
142
 
143
  // allocate a static buffer for the sysctl values, which are typically
144
  // quite short
145
  char buffer[CLS_HOST_SYSCTL_BUFFER_SIZE];
146
 
147
#if TARGET_OS_EMBEDDED
148
  FIRCLSHostWriteSysctlEntry(file, "machine", "hw.model", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);
149
#else
150
  FIRCLSHostWriteSysctlEntry(file, "machine", "hw.machine", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);
151
  FIRCLSHostWriteSysctlEntry(file, "cpu", "machdep.cpu.brand_string", buffer,
152
                             CLS_HOST_SYSCTL_BUFFER_SIZE);
153
#endif
154
}
155
 
156
static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file) {
157
  FIRCLSFileWriteHashEntryString(file, "os_build_version", [FIRCLSHostOSBuildVersion() UTF8String]);
158
  FIRCLSFileWriteHashEntryString(file, "os_display_version",
159
                                 [FIRCLSHostOSDisplayVersion() UTF8String]);
160
  FIRCLSFileWriteHashEntryString(file, "platform", [FIRCLSApplicationGetPlatform() UTF8String]);
161
  FIRCLSFileWriteHashEntryString(file, "firebase_platform",
162
                                 [FIRCLSApplicationGetFirebasePlatform() UTF8String]);
163
}
164
 
165
bool FIRCLSHostRecord(FIRCLSFile* file) {
166
  FIRCLSFileWriteSectionStart(file, "host");
167
 
168
  FIRCLSFileWriteHashStart(file);
169
 
170
  FIRCLSHostWriteModelInfo(file);
171
  FIRCLSHostWriteOSVersionInfo(file);
172
  FIRCLSFileWriteHashEntryString(file, "locale",
173
                                 [[[NSLocale currentLocale] localeIdentifier] UTF8String]);
174
 
175
  FIRCLSFileWriteHashEnd(file);
176
 
177
  FIRCLSFileWriteSectionEnd(file);
178
 
179
  return true;
180
}
181
 
182
void FIRCLSHostWriteDiskUsage(FIRCLSFile* file) {
183
  struct statfs tStats;
184
 
185
  FIRCLSFileWriteSectionStart(file, "storage");
186
 
187
  FIRCLSFileWriteHashStart(file);
188
 
189
  if (statfs(_firclsContext.readonly->host.documentDirectoryPath, &tStats) == 0) {
190
    FIRCLSFileWriteHashEntryUint64(file, "free", tStats.f_bavail * tStats.f_bsize);
191
    FIRCLSFileWriteHashEntryUint64(file, "total", tStats.f_blocks * tStats.f_bsize);
192
  }
193
 
194
  FIRCLSFileWriteHashEnd(file);
195
 
196
  FIRCLSFileWriteSectionEnd(file);
197
}