blob: 041c78d630d61657223dbdace8f0531300a599f8 [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"
17#include "minzip/SysUtil.h"
18#include "minzip/Zip.h"
19#include "mtdutils/mounts.h"
20#include "mtdutils/mtdutils.h"
Dees_Troy32c8eb82012-09-11 15:28:06 -040021#include "verifier.h"
Dees_Troy32c8eb82012-09-11 15:28:06 -040022#include "variables.h"
23#include "data.hpp"
24#include "partitions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050025#include "twrpDigest.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040026#include "twrp-functions.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000027extern "C" {
28 #include "gui/gui.h"
29}
Dees_Troy32c8eb82012-09-11 15:28:06 -040030
Dees_Troy2673cec2013-04-02 20:22:16 +000031static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) {
32 const ZipEntry* binary_location = mzFindZipEntry(Zip, ASSUMED_UPDATE_BINARY_NAME);
33 string Temp_Binary = "/tmp/updater";
34 int binary_fd, ret_val, pipe_fd[2], status, zip_verify;
35 char buffer[1024];
36 const char** args = (const char**)malloc(sizeof(char*) * 5);
37 FILE* child_data;
Dees_Troy32c8eb82012-09-11 15:28:06 -040038
Dees_Troy2673cec2013-04-02 20:22:16 +000039 if (binary_location == NULL) {
40 mzCloseZipArchive(Zip);
41 return INSTALL_CORRUPT;
42 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040043
Dees_Troy2673cec2013-04-02 20:22:16 +000044 // Delete any existing updater
45 if (TWFunc::Path_Exists(Temp_Binary) && unlink(Temp_Binary.c_str()) != 0) {
46 LOGINFO("Unable to unlink '%s'\n", Temp_Binary.c_str());
47 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040048
Dees_Troy2673cec2013-04-02 20:22:16 +000049 binary_fd = creat(Temp_Binary.c_str(), 0755);
50 if (binary_fd < 0) {
51 mzCloseZipArchive(Zip);
52 LOGERR("Could not create file for updater extract in '%s'\n", Temp_Binary.c_str());
53 return INSTALL_ERROR;
54 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040055
Dees_Troy2673cec2013-04-02 20:22:16 +000056 ret_val = mzExtractZipEntryToFile(Zip, binary_location, binary_fd);
57 close(binary_fd);
58 mzCloseZipArchive(Zip);
Dees_Troy32c8eb82012-09-11 15:28:06 -040059
Dees_Troy2673cec2013-04-02 20:22:16 +000060 if (!ret_val) {
61 LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
62 return INSTALL_ERROR;
63 }
Dees_Troy32c8eb82012-09-11 15:28:06 -040064
Dees_Troy2673cec2013-04-02 20:22:16 +000065 pipe(pipe_fd);
Dees_Troy32c8eb82012-09-11 15:28:06 -040066
Dees_Troy2673cec2013-04-02 20:22:16 +000067 args[0] = Temp_Binary.c_str();
68 args[1] = EXPAND(RECOVERY_API_VERSION);
69 char* temp = (char*)malloc(10);
70 sprintf(temp, "%d", pipe_fd[1]);
71 args[2] = temp;
72 args[3] = (char*)path;
73 args[4] = NULL;
Dees_Troy32c8eb82012-09-11 15:28:06 -040074
Dees_Troy2673cec2013-04-02 20:22:16 +000075 pid_t pid = fork();
76 if (pid == 0) {
77 close(pipe_fd[0]);
78 execv(Temp_Binary.c_str(), (char* const*)args);
79 printf("E:Can't execute '%s'\n", Temp_Binary.c_str());
80 _exit(-1);
81 }
82 close(pipe_fd[1]);
Dees_Troy32c8eb82012-09-11 15:28:06 -040083
Dees_Troy2673cec2013-04-02 20:22:16 +000084 *wipe_cache = 0;
Dees_Troy32c8eb82012-09-11 15:28:06 -040085
Dees_Troy2673cec2013-04-02 20:22:16 +000086 DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
87 child_data = fdopen(pipe_fd[0], "r");
88 while (fgets(buffer, sizeof(buffer), child_data) != NULL) {
89 char* command = strtok(buffer, " \n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020090 if (command == NULL) {
91 continue;
92 } else if (strcmp(command, "progress") == 0) {
93 char* fraction_char = strtok(NULL, " \n");
94 char* seconds_char = strtok(NULL, " \n");
Dees_Troy32c8eb82012-09-11 15:28:06 -040095
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020096 float fraction_float = strtof(fraction_char, NULL);
97 int seconds_float = strtol(seconds_char, NULL, 10);
Dees_Troy32c8eb82012-09-11 15:28:06 -040098
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020099 if (zip_verify)
Dees_Troy2673cec2013-04-02 20:22:16 +0000100 DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float);
101 else
102 DataManager::ShowProgress(fraction_float, seconds_float);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200103 } else if (strcmp(command, "set_progress") == 0) {
104 char* fraction_char = strtok(NULL, " \n");
105 float fraction_float = strtof(fraction_char, NULL);
106 DataManager::SetProgress(fraction_float);
107 } else if (strcmp(command, "ui_print") == 0) {
108 char* display_value = strtok(NULL, "\n");
109 if (display_value) {
110 gui_print("%s", display_value);
111 } else {
112 gui_print("\n");
113 }
114 } else if (strcmp(command, "wipe_cache") == 0) {
115 *wipe_cache = 1;
116 } else if (strcmp(command, "clear_display") == 0) {
117 // Do nothing, not supported by TWRP
118 } else {
119 LOGERR("unknown command [%s]\n", command);
120 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000121 }
122 fclose(child_data);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400123
Dees_Troy2673cec2013-04-02 20:22:16 +0000124 waitpid(pid, &status, 0);
125 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
126 LOGERR("Error executing updater binary in zip '%s'\n", path);
127 return INSTALL_ERROR;
128 }
Dees_Troy32c8eb82012-09-11 15:28:06 -0400129
Dees_Troy2673cec2013-04-02 20:22:16 +0000130 return INSTALL_SUCCESS;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400131}
132
Dees_Troy32c8eb82012-09-11 15:28:06 -0400133extern "C" int TWinstall_zip(const char* path, int* wipe_cache) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000134 int ret_val, zip_verify, md5_return, key_count;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500135 twrpDigest md5sum;
136 string strpath = path;
Dees_Troy2673cec2013-04-02 20:22:16 +0000137 ZipArchive Zip;
Dees_Troy32c8eb82012-09-11 15:28:06 -0400138
Dees_Troy2673cec2013-04-02 20:22:16 +0000139 gui_print("Installing '%s'...\nChecking for MD5 file...\n", path);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500140 md5sum.setfn(strpath);
141 md5_return = md5sum.verify_md5digest();
142 if (md5_return == -2) {
Dees_Troy32c8eb82012-09-11 15:28:06 -0400143 // MD5 did not match.
Dees_Troy2673cec2013-04-02 20:22:16 +0000144 LOGERR("Zip MD5 does not match.\nUnable to install zip.\n");
Dees_Troy32c8eb82012-09-11 15:28:06 -0400145 return INSTALL_CORRUPT;
146 } else if (md5_return == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000147 gui_print("Skipping MD5 check: no MD5 file found.\n");
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500148 } else if (md5_return == 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000149 gui_print("Zip MD5 matched.\n"); // MD5 found and matched.
Dees_Troy32c8eb82012-09-11 15:28:06 -0400150
151 DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
Dees_Troy2673cec2013-04-02 20:22:16 +0000152 DataManager::SetProgress(0);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400153 if (zip_verify) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000154 gui_print("Verifying zip signature...\n");
155 ret_val = verify_file(path);
156 if (ret_val != VERIFY_SUCCESS) {
157 LOGERR("Zip signature verification failed: %i\n", ret_val);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400158 return -1;
159 }
160 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000161 ret_val = mzOpenZipArchive(path, &Zip);
162 if (ret_val != 0) {
163 LOGERR("Zip file is corrupt!\n", path);
164 return INSTALL_CORRUPT;
165 }
166 return Run_Update_Binary(path, &Zip, wipe_cache);
Dees_Troy32c8eb82012-09-11 15:28:06 -0400167}