blob: 1b9c23eb4092718adb83f021e15b088002aef2ee [file] [log] [blame]
Dees_Troy32c8eb82012-09-11 15:28:06 -04001
2#include <ctype.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <limits.h>
6#include <sys/stat.h>
7#include <sys/wait.h>
8#include <unistd.h>
9
10#include <string.h>
11#include <stdio.h>
12
Dees_Troy2673cec2013-04-02 20:22:16 +000013#include "twcommon.h"
Dees_Troyb9d88ac2012-09-14 14:34:19 -040014#include "mincrypt/rsa.h"
15#include "mincrypt/sha.h"
Dees_Troy32c8eb82012-09-11 15:28:06 -040016#include "minui/minui.h"
Dees Troyb7ae0982013-09-10 20:47:35 +000017#ifdef HAVE_SELINUX
Dees_Troy32c8eb82012-09-11 15:28:06 -040018#include "minzip/SysUtil.h"
19#include "minzip/Zip.h"
Dees Troyb7ae0982013-09-10 20:47:35 +000020#else
21#include "minzipold/SysUtil.h"
22#include "minzipold/Zip.h"
23#endif
Dees_Troy32c8eb82012-09-11 15:28:06 -040024#include "mtdutils/mounts.h"
25#include "mtdutils/mtdutils.h"
Dees_Troy32c8eb82012-09-11 15:28:06 -040026#include "verifier.h"
Dees_Troy32c8eb82012-09-11 15:28:06 -040027#include "variables.h"
28#include "data.hpp"
29#include "partitions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050030#include "twrpDigest.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040031#include "twrp-functions.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000032extern "C" {
33 #include "gui/gui.h"
34}
Dees_Troy32c8eb82012-09-11 15:28:06 -040035
Dees_Troy2673cec2013-04-02 20:22:16 +000036static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) {
37 const ZipEntry* binary_location = mzFindZipEntry(Zip, ASSUMED_UPDATE_BINARY_NAME);
38 string Temp_Binary = "/tmp/updater";
39 int binary_fd, ret_val, pipe_fd[2], status, zip_verify;
40 char buffer[1024];
41 const char** args = (const char**)malloc(sizeof(char*) * 5);
42 FILE* child_data;
Dees_Troy32c8eb82012-09-11 15:28:06 -040043
Dees_Troy2673cec2013-04-02 20:22:16 +000044 if (binary_location == NULL) {
45 mzCloseZipArchive(Zip);
46 return INSTALL_CORRUPT;
47 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040048
Dees_Troy2673cec2013-04-02 20:22:16 +000049 // Delete any existing updater
50 if (TWFunc::Path_Exists(Temp_Binary) && unlink(Temp_Binary.c_str()) != 0) {
51 LOGINFO("Unable to unlink '%s'\n", Temp_Binary.c_str());
52 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040053
Dees_Troy2673cec2013-04-02 20:22:16 +000054 binary_fd = creat(Temp_Binary.c_str(), 0755);
55 if (binary_fd < 0) {
56 mzCloseZipArchive(Zip);
57 LOGERR("Could not create file for updater extract in '%s'\n", Temp_Binary.c_str());
58 return INSTALL_ERROR;
59 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040060
Dees_Troy2673cec2013-04-02 20:22:16 +000061 ret_val = mzExtractZipEntryToFile(Zip, binary_location, binary_fd);
62 close(binary_fd);
Dees_Troy32c8eb82012-09-11 15:28:06 -040063
Dees_Troy2673cec2013-04-02 20:22:16 +000064 if (!ret_val) {
Dees_Troy512376c2013-09-03 19:39:41 +000065 mzCloseZipArchive(Zip);
Dees_Troy2673cec2013-04-02 20:22:16 +000066 LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
67 return INSTALL_ERROR;
68 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040069
Dees_Troy512376c2013-09-03 19:39:41 +000070 // If exists, extract file_contexts from the zip file
71 const ZipEntry* selinx_contexts = mzFindZipEntry(Zip, "file_contexts");
72 if (selinx_contexts == NULL) {
73 mzCloseZipArchive(Zip);
74 LOGINFO("Zip does not contain SELinux file_contexts file in its root.\n");
75 } else {
76 string output_filename = "/file_contexts";
77 LOGINFO("Zip contains SELinux file_contexts file in its root. Extracting to %s\n", output_filename.c_str());
78 // Delete any file_contexts
79 if (TWFunc::Path_Exists(output_filename) && unlink(output_filename.c_str()) != 0) {
80 LOGINFO("Unable to unlink '%s'\n", output_filename.c_str());
81 }
82
83 int file_contexts_fd = creat(output_filename.c_str(), 0644);
84 if (file_contexts_fd < 0) {
85 mzCloseZipArchive(Zip);
86 LOGERR("Could not extract file_contexts to '%s'\n", output_filename.c_str());
87 return INSTALL_ERROR;
88 }
89
90 ret_val = mzExtractZipEntryToFile(Zip, selinx_contexts, file_contexts_fd);
91 close(file_contexts_fd);
92
93 if (!ret_val) {
94 mzCloseZipArchive(Zip);
95 LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
96 return INSTALL_ERROR;
97 }
98 }
99 mzCloseZipArchive(Zip);
100
Dees_Troy2673cec2013-04-02 20:22:16 +0000101 pipe(pipe_fd);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400102
Dees_Troy2673cec2013-04-02 20:22:16 +0000103 args[0] = Temp_Binary.c_str();
104 args[1] = EXPAND(RECOVERY_API_VERSION);
105 char* temp = (char*)malloc(10);
106 sprintf(temp, "%d", pipe_fd[1]);
107 args[2] = temp;
108 args[3] = (char*)path;
109 args[4] = NULL;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400110
Dees_Troy2673cec2013-04-02 20:22:16 +0000111 pid_t pid = fork();
112 if (pid == 0) {
113 close(pipe_fd[0]);
114 execv(Temp_Binary.c_str(), (char* const*)args);
115 printf("E:Can't execute '%s'\n", Temp_Binary.c_str());
116 _exit(-1);
117 }
118 close(pipe_fd[1]);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400119
Dees_Troy2673cec2013-04-02 20:22:16 +0000120 *wipe_cache = 0;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400121
Dees_Troy2673cec2013-04-02 20:22:16 +0000122 DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
123 child_data = fdopen(pipe_fd[0], "r");
124 while (fgets(buffer, sizeof(buffer), child_data) != NULL) {
125 char* command = strtok(buffer, " \n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200126 if (command == NULL) {
127 continue;
128 } else if (strcmp(command, "progress") == 0) {
129 char* fraction_char = strtok(NULL, " \n");
130 char* seconds_char = strtok(NULL, " \n");
Dees_Troy32c8eb82012-09-11 15:28:06 -0400131
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200132 float fraction_float = strtof(fraction_char, NULL);
133 int seconds_float = strtol(seconds_char, NULL, 10);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400134
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200135 if (zip_verify)
Dees_Troy2673cec2013-04-02 20:22:16 +0000136 DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float);
137 else
138 DataManager::ShowProgress(fraction_float, seconds_float);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200139 } else if (strcmp(command, "set_progress") == 0) {
140 char* fraction_char = strtok(NULL, " \n");
141 float fraction_float = strtof(fraction_char, NULL);
142 DataManager::SetProgress(fraction_float);
143 } else if (strcmp(command, "ui_print") == 0) {
144 char* display_value = strtok(NULL, "\n");
145 if (display_value) {
146 gui_print("%s", display_value);
147 } else {
148 gui_print("\n");
149 }
150 } else if (strcmp(command, "wipe_cache") == 0) {
151 *wipe_cache = 1;
152 } else if (strcmp(command, "clear_display") == 0) {
153 // Do nothing, not supported by TWRP
154 } else {
155 LOGERR("unknown command [%s]\n", command);
156 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000157 }
158 fclose(child_data);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400159
Dees_Troy2673cec2013-04-02 20:22:16 +0000160 waitpid(pid, &status, 0);
161 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
162 LOGERR("Error executing updater binary in zip '%s'\n", path);
163 return INSTALL_ERROR;
164 }
Dees_Troy32c8eb82012-09-11 15:28:06 -0400165
Dees_Troy2673cec2013-04-02 20:22:16 +0000166 return INSTALL_SUCCESS;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400167}
168
Dees_Troy32c8eb82012-09-11 15:28:06 -0400169extern "C" int TWinstall_zip(const char* path, int* wipe_cache) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000170 int ret_val, zip_verify, md5_return, key_count;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500171 twrpDigest md5sum;
172 string strpath = path;
Dees_Troy2673cec2013-04-02 20:22:16 +0000173 ZipArchive Zip;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400174
Dees_Troy2673cec2013-04-02 20:22:16 +0000175 gui_print("Installing '%s'...\nChecking for MD5 file...\n", path);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500176 md5sum.setfn(strpath);
177 md5_return = md5sum.verify_md5digest();
178 if (md5_return == -2) {
Dees_Troy32c8eb82012-09-11 15:28:06 -0400179 // MD5 did not match.
Dees_Troy2673cec2013-04-02 20:22:16 +0000180 LOGERR("Zip MD5 does not match.\nUnable to install zip.\n");
Dees_Troy32c8eb82012-09-11 15:28:06 -0400181 return INSTALL_CORRUPT;
182 } else if (md5_return == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000183 gui_print("Skipping MD5 check: no MD5 file found.\n");
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500184 } else if (md5_return == 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000185 gui_print("Zip MD5 matched.\n"); // MD5 found and matched.
Dees_Troy32c8eb82012-09-11 15:28:06 -0400186
187 DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
Dees_Troy2673cec2013-04-02 20:22:16 +0000188 DataManager::SetProgress(0);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400189 if (zip_verify) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000190 gui_print("Verifying zip signature...\n");
191 ret_val = verify_file(path);
192 if (ret_val != VERIFY_SUCCESS) {
193 LOGERR("Zip signature verification failed: %i\n", ret_val);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400194 return -1;
195 }
196 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000197 ret_val = mzOpenZipArchive(path, &Zip);
198 if (ret_val != 0) {
199 LOGERR("Zip file is corrupt!\n", path);
200 return INSTALL_CORRUPT;
201 }
202 return Run_Update_Binary(path, &Zip, wipe_cache);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400203}