blob: 52dd9e502099e26a72ff40b8e7d77627992f6e03 [file] [log] [blame]
bigbiff6411e082020-09-14 20:13:12 -04001#include "twrpApex.hpp"
bigbiff0e97f7e2021-02-25 10:16:59 -05002#include "twrp-functions.hpp"
bigbiff6411e082020-09-14 20:13:12 -04003
4namespace fs = std::filesystem;
5
6bool twrpApex::loadApexImages() {
7 std::vector<std::string> apexFiles;
8 if (access(APEX_DIR, F_OK) != 0) {
9 LOGERR("Unable to open %s\n", APEX_DIR);
10 return false;
11 }
12 for (const auto& entry : fs::directory_iterator(APEX_DIR)) {
13 if (entry.is_regular_file()) {
14 apexFiles.push_back(entry.path().string());
15 }
16 }
17
18 if (apexFiles.size() == 0) {
19 // flattened apex directory
20 LOGINFO("Bind mounting flattened apex directory\n");
21 if (mount(APEX_DIR, APEX_BASE, "", MS_BIND, NULL) < 0) {
22 LOGERR("Unable to bind mount flattened apex directory\n");
23 return false;
24 }
25 return true;
26 }
bigbiff0e97f7e2021-02-25 10:16:59 -050027 if (!mountApexOnLoopbackDevices(apexFiles)) {
bigbiff6411e082020-09-14 20:13:12 -040028 LOGERR("Unable to create loop devices to mount apex files\n");
29 return false;
30 }
31
bigbiff6411e082020-09-14 20:13:12 -040032 return true;
33}
34
35std::string twrpApex::unzipImage(std::string file) {
36 ZipArchiveHandle handle;
37 int32_t ret = OpenArchive(file.c_str(), &handle);
38 if (ret != 0) {
39 LOGERR("unable to open zip archive %s\n", file.c_str());
40 CloseArchive(handle);
41 return nullptr;
42 }
43
44 ZipEntry entry;
bigbiff673c7ae2020-12-02 19:44:56 -050045 std::string zip_string(APEX_PAYLOAD);
bigbiff6411e082020-09-14 20:13:12 -040046 ret = FindEntry(handle, zip_string, &entry);
47 if (ret != 0) {
48 LOGERR("unable to find %s in zip\n", APEX_PAYLOAD);
49 CloseArchive(handle);
50 return nullptr;
51 }
52
53 std::string baseFile = basename(file.c_str());
54 std::string path("/tmp/");
55 path = path + baseFile;
56 int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
57 ret = ExtractEntryToFile(handle, &entry, fd);
58 if (ret != 0) {
59 LOGERR("unable to extract %s\n", path.c_str());
60 close(fd);
61 CloseArchive(handle);
62 return nullptr;
63 }
64
bigbiff6411e082020-09-14 20:13:12 -040065 CloseArchive(handle);
bigbiff0e97f7e2021-02-25 10:16:59 -050066 close(fd);
bigbiff6411e082020-09-14 20:13:12 -040067 return path;
68}
69
bigbiff0e97f7e2021-02-25 10:16:59 -050070bool twrpApex::mountApexOnLoopbackDevices(std::vector<std::string> apexFiles) {
71 int fd = open(LOOP_CONTROL, O_RDWR | O_CLOEXEC);
72 if (fd < 0) {
73 LOGERR("Unable to open %s device. Reason: %s\n", LOOP_CONTROL, strerror(errno));
74 return false;
bigbiff6411e082020-09-14 20:13:12 -040075 }
76
bigbiff0e97f7e2021-02-25 10:16:59 -050077 size_t device_no = 0;
78 for (auto&& apexFile:apexFiles) {
79 int num = ioctl(fd, LOOP_CTL_GET_FREE);
80 std::string loop_device = LOOP_BLOCK_DEVICE_DIR;
81 loop_device = loop_device + "loop" + std::to_string(num);
82 if (!TWFunc::Path_Exists(loop_device)) {
83 int ret = mknod(loop_device.c_str(), S_IFBLK | S_IRUSR | S_IWUSR , makedev(7, device_no));
bigbiff6411e082020-09-14 20:13:12 -040084 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -050085 LOGERR("Unable to create loop device: %s\n", loop_device.c_str());
bigbiff6411e082020-09-14 20:13:12 -040086 return false;
87 }
88 }
bigbiff0e97f7e2021-02-25 10:16:59 -050089 std::string fileToMount = unzipImage(apexFile);
90 bool load_result = loadApexImage(fileToMount, device_no);
91 if (!load_result) {
92 return false;
93 }
94 device_no++;
bigbiff6411e082020-09-14 20:13:12 -040095 }
96 return true;
97}
98
99bool twrpApex::loadApexImage(std::string fileToMount, size_t loop_device_number) {
100 struct loop_info64 info;
101
bigbiff0e97f7e2021-02-25 10:16:59 -0500102 int fd = open(fileToMount.c_str(), O_RDONLY | O_CLOEXEC);
bigbiff6411e082020-09-14 20:13:12 -0400103 if (fd < 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500104 LOGERR("unable to open apex file: %s. Reason: %s\n", fileToMount.c_str(), strerror(errno));
bigbiff6411e082020-09-14 20:13:12 -0400105 return false;
106 }
107
108 std::string loop_device = "/dev/block/loop" + std::to_string(loop_device_number);
109 int loop_fd = open(loop_device.c_str(), O_RDONLY);
110 if (loop_fd < 0) {
111 LOGERR("unable to open loop device: %s\n", loop_device.c_str());
112 close(fd);
113 return false;
114 }
115
116 if (ioctl(loop_fd, LOOP_SET_FD, fd) < 0) {
117 LOGERR("failed to mount %s to loop device %s\n", fileToMount.c_str(), loop_device.c_str());
118 close(fd);
119 close(loop_fd);
120 return false;
121 }
122
123 close(fd);
124
125 memset(&info, 0, sizeof(struct loop_info64));
bigbiff0e97f7e2021-02-25 10:16:59 -0500126 strlcpy((char*)info.lo_crypt_name, "twrpApex", LO_NAME_SIZE);
127 off_t apex_size = lseek(fd, 0, SEEK_END);
128 info.lo_sizelimit = apex_size;
bigbiff6411e082020-09-14 20:13:12 -0400129 if (ioctl(loop_fd, LOOP_SET_STATUS64, &info)) {
130 LOGERR("failed to mount loop: %s: %s\n", fileToMount.c_str(), strerror(errno));
131 close(loop_fd);
132 return false;
133 }
bigbiff0e97f7e2021-02-25 10:16:59 -0500134 if (ioctl(loop_fd, BLKFLSBUF, 0) == -1) {
135 LOGERR("Unable to flush loop device buffers\n");
136 return false;
137 }
138 if (ioctl(loop_fd, LOOP_SET_BLOCK_SIZE, 4096) == -1) {
139 LOGINFO("Failed to set DIRECT_IO buffer size\n");
140 }
bigbiff6411e082020-09-14 20:13:12 -0400141 close(loop_fd);
bigbiff0e97f7e2021-02-25 10:16:59 -0500142
bigbiff6411e082020-09-14 20:13:12 -0400143 std::string bind_mount(APEX_BASE);
144 bind_mount = bind_mount + basename(fileToMount.c_str());
bigbiff0e97f7e2021-02-25 10:16:59 -0500145
bigbiff6411e082020-09-14 20:13:12 -0400146 int ret = mkdir(bind_mount.c_str(), 0666);
147 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500148 LOGERR("Unable to create bind mount directory: %s\n", bind_mount.c_str());
bigbiff6411e082020-09-14 20:13:12 -0400149 return false;
150 }
151
152 ret = mount(loop_device.c_str(), bind_mount.c_str(), "ext4", MS_RDONLY, nullptr);
153 if (ret != 0) {
bigbiff0e97f7e2021-02-25 10:16:59 -0500154 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 -0400155 return false;
156 }
157
158 return true;
159}