blob: 45e3e30b76e4a1ab599fafffe2f907f691ac1887 [file] [log] [blame]
bigbiff6411e082020-09-14 20:13:12 -04001#include "twrpApex.hpp"
bigbiff0e97f7e2021-02-25 10:16:59 -05002#include "twrp-functions.hpp"
bigbiff79924302021-05-02 20:06:09 -04003#include "common.h"
bigbiff6411e082020-09-14 20:13:12 -04004
5namespace fs = std::filesystem;
6
7bool twrpApex::loadApexImages() {
8 std::vector<std::string> apexFiles;
bigbiff79924302021-05-02 20:06:09 -04009 std::vector<std::string> checkApexFlatFiles;
10#ifdef TW_ADDITIONAL_APEX_FILES
11 char* additionalFiles = strdup(EXPAND(TW_ADDITIONAL_APEX_FILES));
12 char* additionalApexFiles = std::strtok(additionalFiles, " ");
13#endif
14
15 apexFiles.push_back(APEX_DIR "/com.android.apex.cts.shim.apex");
16 apexFiles.push_back(APEX_DIR "/com.google.android.tzdata2.apex");
17 apexFiles.push_back(APEX_DIR "/com.android.tzdata.apex");
18 apexFiles.push_back(APEX_DIR "/com.android.art.release.apex");
19 apexFiles.push_back(APEX_DIR "/com.google.android.media.swcodec.apex");
20 apexFiles.push_back(APEX_DIR "/com.android.media.swcodec.apex");
21
22#ifdef TW_ADDITIONAL_APEX_FILES
23 while(additionalApexFiles) {
24 std::stringstream apexFile;
25 apexFile << APEX_DIR << "/" << additionalApexFiles;
26 apexFiles.push_back(apexFile.str());
27 additionalApexFiles = std::strtok(nullptr, " ");
28 }
29#endif
30
bigbiff6411e082020-09-14 20:13:12 -040031 if (access(APEX_DIR, F_OK) != 0) {
32 LOGERR("Unable to open %s\n", APEX_DIR);
33 return false;
34 }
35 for (const auto& entry : fs::directory_iterator(APEX_DIR)) {
36 if (entry.is_regular_file()) {
bigbiff79924302021-05-02 20:06:09 -040037 checkApexFlatFiles.push_back(entry.path().string());
bigbiff6411e082020-09-14 20:13:12 -040038 }
39 }
40
bigbiff79924302021-05-02 20:06:09 -040041 if (checkApexFlatFiles.size() == 0) {
bigbiff6411e082020-09-14 20:13:12 -040042 // flattened apex directory
43 LOGINFO("Bind mounting flattened apex directory\n");
44 if (mount(APEX_DIR, APEX_BASE, "", MS_BIND, NULL) < 0) {
45 LOGERR("Unable to bind mount flattened apex directory\n");
46 return false;
47 }
48 return true;
49 }
bigbiff0e97f7e2021-02-25 10:16:59 -050050 if (!mountApexOnLoopbackDevices(apexFiles)) {
bigbiff6411e082020-09-14 20:13:12 -040051 LOGERR("Unable to create loop devices to mount apex files\n");
52 return false;
53 }
54
bigbiff6411e082020-09-14 20:13:12 -040055 return true;
56}
57
58std::string twrpApex::unzipImage(std::string file) {
59 ZipArchiveHandle handle;
60 int32_t ret = OpenArchive(file.c_str(), &handle);
61 if (ret != 0) {
bigbiff79924302021-05-02 20:06:09 -040062 LOGINFO("unable to open zip archive %s. Reason: %s\n", file.c_str(), strerror(errno));
63 return std::string();
bigbiff6411e082020-09-14 20:13:12 -040064 }
65
66 ZipEntry entry;
bigbiff673c7ae2020-12-02 19:44:56 -050067 std::string zip_string(APEX_PAYLOAD);
bigbiff6411e082020-09-14 20:13:12 -040068 ret = FindEntry(handle, zip_string, &entry);
69 if (ret != 0) {
70 LOGERR("unable to find %s in zip\n", APEX_PAYLOAD);
71 CloseArchive(handle);
bigbiff79924302021-05-02 20:06:09 -040072 return std::string();
bigbiff6411e082020-09-14 20:13:12 -040073 }
74
75 std::string baseFile = basename(file.c_str());
76 std::string path("/tmp/");
77 path = path + baseFile;
78 int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
79 ret = ExtractEntryToFile(handle, &entry, fd);
80 if (ret != 0) {
81 LOGERR("unable to extract %s\n", path.c_str());
82 close(fd);
83 CloseArchive(handle);
bigbiff79924302021-05-02 20:06:09 -040084 return std::string();
bigbiff6411e082020-09-14 20:13:12 -040085 }
86
bigbiff6411e082020-09-14 20:13:12 -040087 CloseArchive(handle);
bigbiff0e97f7e2021-02-25 10:16:59 -050088 close(fd);
bigbiff6411e082020-09-14 20:13:12 -040089 return path;
90}
91
bigbiff0e97f7e2021-02-25 10:16:59 -050092bool twrpApex::mountApexOnLoopbackDevices(std::vector<std::string> apexFiles) {
93 int fd = open(LOOP_CONTROL, O_RDWR | O_CLOEXEC);
94 if (fd < 0) {
95 LOGERR("Unable to open %s device. Reason: %s\n", LOOP_CONTROL, strerror(errno));
96 return false;
bigbiff6411e082020-09-14 20:13:12 -040097 }
98
bigbiff0e97f7e2021-02-25 10:16:59 -050099 size_t device_no = 0;
100 for (auto&& apexFile:apexFiles) {
101 int num = ioctl(fd, LOOP_CTL_GET_FREE);
102 std::string loop_device = LOOP_BLOCK_DEVICE_DIR;
103 loop_device = loop_device + "loop" + std::to_string(num);
104 if (!TWFunc::Path_Exists(loop_device)) {
105 int ret = mknod(loop_device.c_str(), S_IFBLK | S_IRUSR | S_IWUSR , makedev(7, device_no));
bigbiff6411e082020-09-14 20:13:12 -0400106 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500107 LOGERR("Unable to create loop device: %s\n", loop_device.c_str());
bigbiff6411e082020-09-14 20:13:12 -0400108 return false;
109 }
110 }
bigbiff0e97f7e2021-02-25 10:16:59 -0500111 std::string fileToMount = unzipImage(apexFile);
bigbiff79924302021-05-02 20:06:09 -0400112 if (fileToMount.empty()) {
113 LOGINFO("Skipping non-existent apex file: %s\n", apexFile.c_str());
114 continue;
115 }
bigbiff0e97f7e2021-02-25 10:16:59 -0500116 bool load_result = loadApexImage(fileToMount, device_no);
117 if (!load_result) {
118 return false;
119 }
120 device_no++;
bigbiff6411e082020-09-14 20:13:12 -0400121 }
122 return true;
123}
124
125bool twrpApex::loadApexImage(std::string fileToMount, size_t loop_device_number) {
126 struct loop_info64 info;
127
bigbiff0e97f7e2021-02-25 10:16:59 -0500128 int fd = open(fileToMount.c_str(), O_RDONLY | O_CLOEXEC);
bigbiff6411e082020-09-14 20:13:12 -0400129 if (fd < 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500130 LOGERR("unable to open apex file: %s. Reason: %s\n", fileToMount.c_str(), strerror(errno));
bigbiff6411e082020-09-14 20:13:12 -0400131 return false;
132 }
133
134 std::string loop_device = "/dev/block/loop" + std::to_string(loop_device_number);
135 int loop_fd = open(loop_device.c_str(), O_RDONLY);
136 if (loop_fd < 0) {
137 LOGERR("unable to open loop device: %s\n", loop_device.c_str());
138 close(fd);
139 return false;
140 }
141
142 if (ioctl(loop_fd, LOOP_SET_FD, fd) < 0) {
bigbiff79924302021-05-02 20:06:09 -0400143 LOGERR("failed to mount %s to loop device %s. Reason: %s\n", fileToMount.c_str(), loop_device.c_str(),
144 strerror(errno));
bigbiff6411e082020-09-14 20:13:12 -0400145 close(fd);
146 close(loop_fd);
147 return false;
148 }
149
150 close(fd);
151
152 memset(&info, 0, sizeof(struct loop_info64));
bigbiff0e97f7e2021-02-25 10:16:59 -0500153 strlcpy((char*)info.lo_crypt_name, "twrpApex", LO_NAME_SIZE);
154 off_t apex_size = lseek(fd, 0, SEEK_END);
155 info.lo_sizelimit = apex_size;
bigbiff6411e082020-09-14 20:13:12 -0400156 if (ioctl(loop_fd, LOOP_SET_STATUS64, &info)) {
157 LOGERR("failed to mount loop: %s: %s\n", fileToMount.c_str(), strerror(errno));
158 close(loop_fd);
159 return false;
160 }
bigbiff0e97f7e2021-02-25 10:16:59 -0500161 if (ioctl(loop_fd, BLKFLSBUF, 0) == -1) {
162 LOGERR("Unable to flush loop device buffers\n");
163 return false;
164 }
165 if (ioctl(loop_fd, LOOP_SET_BLOCK_SIZE, 4096) == -1) {
166 LOGINFO("Failed to set DIRECT_IO buffer size\n");
167 }
bigbiff6411e082020-09-14 20:13:12 -0400168 close(loop_fd);
bigbiff0e97f7e2021-02-25 10:16:59 -0500169
bigbiff6411e082020-09-14 20:13:12 -0400170 std::string bind_mount(APEX_BASE);
171 bind_mount = bind_mount + basename(fileToMount.c_str());
bigbiff0e97f7e2021-02-25 10:16:59 -0500172
bigbiff6411e082020-09-14 20:13:12 -0400173 int ret = mkdir(bind_mount.c_str(), 0666);
174 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500175 LOGERR("Unable to create bind mount directory: %s\n", bind_mount.c_str());
bigbiff6411e082020-09-14 20:13:12 -0400176 return false;
177 }
178
179 ret = mount(loop_device.c_str(), bind_mount.c_str(), "ext4", MS_RDONLY, nullptr);
180 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500181 LOGERR("unable to mount loop device %s to %s. Reason: %s\n", loop_device.c_str(), bind_mount.c_str(), strerror(errno));
bigbiff6411e082020-09-14 20:13:12 -0400182 return false;
183 }
184
185 return true;
186}