-
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmac_impl.cpp
More file actions
143 lines (130 loc) · 5.09 KB
/
mac_impl.cpp
File metadata and controls
143 lines (130 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef _WIN32
#include "CommonFunctions.h"
#include "Constants.h"
#include "Declarations.h"
#include "StringHelper.h"
#include "dirent.h"
#include <array>
#include <map>
#include <regex>
extern std::map<std::string, DeviceData> devices;
std::string exec(const char *cmd) {
std::array<char, 128> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe)
return "";
while (!feof(pipe.get())) {
if (fgets(buffer.data(), 128, pipe.get()) != NULL) {
result += buffer.data();
}
}
return result;
}
int get_product_version(std::string &device_identifier){
std::string product_version =
get_device_property_value(device_identifier, kProductVersion);
return std::stoi(product_version);
}
int get_xcode_major_version(){
std::string cmd_result = exec("xcodebuild -version");
if(cmd_result.length()>0){
std::regex versionRegex("Xcode (\\d+)");
std::smatch match;
if (std::regex_search(cmd_result, match, versionRegex)) {
std::string xcodeVersion = match[1].str();
return std::stoi(xcodeVersion);
}
}
return -1;
}
std::string
get_developer_disk_image_directory_path(std::string &device_identifier) {
if (!devices.count(device_identifier)) {
return "";
}
std::string dev_dir_path = exec("xcode-select -print-path");
dev_dir_path =
trim_end(dev_dir_path) + "/Platforms/iPhoneOS.platform/DeviceSupport";
std::string build_version =
get_device_property_value(device_identifier, "BuildVersion");
std::string product_version =
get_device_property_value(device_identifier, kProductVersion);
std::vector<std::string> product_version_parts = split(product_version, '.');
std::string product_major_version = product_version_parts[0];
std::string product_minor_version = product_version_parts[1];
std::string result = "";
DIR *dir;
struct dirent *ent;
if ((dir = opendir(dev_dir_path.c_str())) != NULL) {
// The contents of this directory are named like this
// <Major>.<Minor>[ (<Build>)]
// 9.0
// 9.1 (13B137)
while ((ent = readdir(dir)) != NULL) {
std::vector<std::string> parts = split(ent->d_name, ' ');
std::vector<std::string> version_parts = split(parts[0], '.');
std::string major_version = version_parts[0];
std::string minor_version = version_parts[1];
std::string build =
parts.size() > 1 ? parts[1].substr(1, parts[1].size() - 2) : "";
if (major_version == product_major_version) {
if (!result.size()) {
result = dev_dir_path + kUnixPathSeparator + ent->d_name;
} else {
// is this better than the last match?
if (minor_version == product_minor_version) {
if (build == build_version) {
// it won't get better than this
return dev_dir_path + kUnixPathSeparator + ent->d_name;
} else {
// major and minor match - consider this better off than last time
result = dev_dir_path + kUnixPathSeparator + ent->d_name;
}
}
}
}
}
closedir(dir);
}
return result;
}
bool mount_image(std::string &device_identifier, std::string &image_path,
std::string &method_id) {
std::string developer_disk_image_directory_path =
get_developer_disk_image_directory_path(device_identifier);
std::string osx_image_path = developer_disk_image_directory_path +
kUnixPathSeparator + "DeveloperDiskImage.dmg";
std::string osx_image_signature_path = osx_image_path + ".signature";
start_session(device_identifier);
FILE *sig = fopen(osx_image_signature_path.c_str(), "rb");
// Signature files ALWAYS have a size of exactly 128 bytes
void *sig_buffer = malloc(128);
bool managed_to_read_signature = fread(sig_buffer, 1, 128, sig) == 128;
fclose(sig);
if (!managed_to_read_signature) {
return false;
}
CFDataRef sig_data =
CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)sig_buffer, 128, NULL);
CFStringRef cf_image_path = create_CFString(osx_image_path.c_str());
const void *keys_arr[] = {CFSTR("ImageType"), CFSTR("ImageSignature")};
const void *values_arr[] = {CFSTR("Developer"), sig_data};
CFDictionaryRef options = CFDictionaryCreate(
NULL, keys_arr, values_arr, 2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// The second-to-last argument is actually a function that is invoked
// periodically as to update the status Its first argument is a pointer to
// Plist object that when deserialized has a Status property which tells us
// how far down the road we've come Currently we do not need progress
// indication of this operation so I'm passing nullptr here
unsigned result = AMDeviceMountImage(devices[device_identifier].device_info,
cf_image_path, options, nullptr, NULL);
stop_session(device_identifier);
CFRelease(sig_data);
CFRelease(cf_image_path);
CFRelease(options);
return result == 0 || result == kIncompatibleSignature ||
result == kMountImageAlreadyMounted;
}
#endif // !_WIN32