blob: e468655a676d7d9584ca9c3a22b5203ac028974c [file] [log] [blame]
Dees_Troy38bd7602012-09-14 13:33:53 -04001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
Dees_Troy38bd7602012-09-14 13:33:53 -04004#include <unistd.h>
5#include <vector>
6#include <dirent.h>
7#include <time.h>
Dees_Troy43d8b002012-09-17 16:00:01 -04008#include <errno.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -05009#include <fcntl.h>
10#include <sys/mount.h>
Dees_Troya58bead2012-09-27 09:49:29 -040011#include <sys/reboot.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050012#include <sys/sendfile.h>
13#include <sys/stat.h>
14#include <sys/vfs.h>
Dees_Troy83bd4832013-05-04 12:39:56 +000015#include <sys/types.h>
16#include <sys/wait.h>
Dees_Troya4438782013-02-22 18:44:00 +000017#ifdef ANDROID_RB_POWEROFF
18 #include "cutils/android_reboot.h"
19#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -050020#include <iostream>
21#include <fstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000022#include <sstream>
Dees_Troy38bd7602012-09-14 13:33:53 -040023#include "twrp-functions.hpp"
24#include "partitions.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000025#include "twcommon.h"
Dees_Troyb46a6842012-09-25 11:06:46 -040026#include "data.hpp"
Dees_Troy3477d712012-09-27 15:44:01 -040027#include "variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000028#include "bootloader.h"
Dees_Troy83bd4832013-05-04 12:39:56 +000029#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
30 #include "openaes/inc/oaes_lib.h"
31#endif
Dees_Troy38bd7602012-09-14 13:33:53 -040032
Dees_Troyb05ddee2013-01-28 20:24:50 +000033extern "C" {
34 #include "libcrecovery/common.h"
35}
36
bigbiff bigbiff9c754052013-01-09 09:09:08 -050037/* Execute a command */
Vojtech Bocek05534202013-09-11 08:11:56 +020038int TWFunc::Exec_Cmd(const string& cmd, string &result) {
Dees_Troy29a06352013-08-24 12:06:47 +000039 FILE* exec;
40 char buffer[130];
41 int ret = 0;
42 exec = __popen(cmd.c_str(), "r");
43 if (!exec) return -1;
44 while(!feof(exec)) {
45 memset(&buffer, 0, sizeof(buffer));
46 if (fgets(buffer, 128, exec) != NULL) {
47 buffer[128] = '\n';
48 buffer[129] = NULL;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050049 result += buffer;
Dees_Troyb05ddee2013-01-28 20:24:50 +000050 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -050051 }
Dees_Troy29a06352013-08-24 12:06:47 +000052 ret = __pclose(exec);
53 return ret;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050054}
55
Vojtech Bocek05534202013-09-11 08:11:56 +020056int TWFunc::Exec_Cmd(const string& cmd) {
57 pid_t pid;
58 int status;
59 switch(pid = fork())
60 {
61 case -1:
62 LOGERR("Exec_Cmd(): vfork failed!\n");
63 return -1;
64 case 0: // child
65 execl("/sbin/sh", "sh", "-c", cmd.c_str(), NULL);
66 _exit(127);
67 break;
68 default:
69 {
70 if (TWFunc::Wait_For_Child(pid, &status, cmd) != 0)
71 return -1;
72 else
73 return 0;
74 }
75 }
76}
77
Dees_Troy38bd7602012-09-14 13:33:53 -040078// Returns "file.name" from a full /path/to/file.name
79string TWFunc::Get_Filename(string Path) {
80 size_t pos = Path.find_last_of("/");
81 if (pos != string::npos) {
82 string Filename;
83 Filename = Path.substr(pos + 1, Path.size() - pos - 1);
84 return Filename;
85 } else
86 return Path;
87}
88
89// Returns "/path/to/" from a full /path/to/file.name
90string TWFunc::Get_Path(string Path) {
91 size_t pos = Path.find_last_of("/");
92 if (pos != string::npos) {
93 string Pathonly;
94 Pathonly = Path.substr(0, pos + 1);
95 return Pathonly;
96 } else
97 return Path;
98}
99
100// Returns "/path" from a full /path/to/file.name
101string TWFunc::Get_Root_Path(string Path) {
102 string Local_Path = Path;
103
104 // Make sure that we have a leading slash
105 if (Local_Path.substr(0, 1) != "/")
106 Local_Path = "/" + Local_Path;
107
108 // Trim the path to get the root path only
109 size_t position = Local_Path.find("/", 2);
110 if (position != string::npos) {
111 Local_Path.resize(position);
112 }
113 return Local_Path;
114}
115
116void TWFunc::install_htc_dumlock(void) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400117 int need_libs = 0;
118
119 if (!PartitionManager.Mount_By_Path("/system", true))
120 return;
121
122 if (!PartitionManager.Mount_By_Path("/data", true))
123 return;
124
Dees_Troy2673cec2013-04-02 20:22:16 +0000125 gui_print("Installing HTC Dumlock to system...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500126 copy_file("/res/htcd/htcdumlocksys", "/system/bin/htcdumlock", 0755);
Dees_Troy8170a922012-09-18 15:40:25 -0400127 if (!Path_Exists("/system/bin/flash_image")) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000128 gui_print("Installing flash_image...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500129 copy_file("/res/htcd/flash_imagesys", "/system/bin/flash_image", 0755);
Dees_Troy38bd7602012-09-14 13:33:53 -0400130 need_libs = 1;
131 } else
Dees_Troy2673cec2013-04-02 20:22:16 +0000132 gui_print("flash_image is already installed, skipping...\n");
Dees_Troy8170a922012-09-18 15:40:25 -0400133 if (!Path_Exists("/system/bin/dump_image")) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000134 gui_print("Installing dump_image...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500135 copy_file("/res/htcd/dump_imagesys", "/system/bin/dump_image", 0755);
Dees_Troy38bd7602012-09-14 13:33:53 -0400136 need_libs = 1;
137 } else
Dees_Troy2673cec2013-04-02 20:22:16 +0000138 gui_print("dump_image is already installed, skipping...\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400139 if (need_libs) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000140 gui_print("Installing libs needed for flash_image and dump_image...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500141 copy_file("/res/htcd/libbmlutils.so", "/system/lib/libbmlutils.so", 0755);
142 copy_file("/res/htcd/libflashutils.so", "/system/lib/libflashutils.so", 0755);
143 copy_file("/res/htcd/libmmcutils.so", "/system/lib/libmmcutils.so", 0755);
144 copy_file("/res/htcd/libmtdutils.so", "/system/lib/libmtdutils.so", 0755);
Dees_Troy38bd7602012-09-14 13:33:53 -0400145 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000146 gui_print("Installing HTC Dumlock app...\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400147 mkdir("/data/app", 0777);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500148 unlink("/data/app/com.teamwin.htcdumlock*");
149 copy_file("/res/htcd/HTCDumlock.apk", "/data/app/com.teamwin.htcdumlock.apk", 0777);
Dees_Troy38bd7602012-09-14 13:33:53 -0400150 sync();
Dees_Troy2673cec2013-04-02 20:22:16 +0000151 gui_print("HTC Dumlock is installed.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400152}
153
154void TWFunc::htc_dumlock_restore_original_boot(void) {
155 if (!PartitionManager.Mount_By_Path("/sdcard", true))
156 return;
157
Dees_Troy2673cec2013-04-02 20:22:16 +0000158 gui_print("Restoring original boot...\n");
Vojtech Bocek05534202013-09-11 08:11:56 +0200159 Exec_Cmd("htcdumlock restore");
Dees_Troy2673cec2013-04-02 20:22:16 +0000160 gui_print("Original boot restored.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400161}
162
163void TWFunc::htc_dumlock_reflash_recovery_to_boot(void) {
164 if (!PartitionManager.Mount_By_Path("/sdcard", true))
165 return;
Dees_Troy2673cec2013-04-02 20:22:16 +0000166 gui_print("Reflashing recovery to boot...\n");
Vojtech Bocek05534202013-09-11 08:11:56 +0200167 Exec_Cmd("htcdumlock recovery noreboot");
Dees_Troy2673cec2013-04-02 20:22:16 +0000168 gui_print("Recovery is flashed to boot.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400169}
Dees_Troy43d8b002012-09-17 16:00:01 -0400170
171int TWFunc::Recursive_Mkdir(string Path) {
172 string pathCpy = Path;
173 string wholePath;
174 size_t pos = pathCpy.find("/", 2);
175
176 while (pos != string::npos)
177 {
178 wholePath = pathCpy.substr(0, pos);
179 if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000180 LOGERR("Unable to create folder: %s (errno=%d)\n", wholePath.c_str(), errno);
Dees_Troy43d8b002012-09-17 16:00:01 -0400181 return false;
182 }
183
184 pos = pathCpy.find("/", pos + 1);
185 }
186 if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST)
187 return false;
188 return true;
189}
190
Vojtech Bocek2e97ec52013-02-02 13:22:42 +0100191unsigned long long TWFunc::Get_Folder_Size(const string& Path, bool Display_Error) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400192 DIR* d;
193 struct dirent* de;
194 struct stat st;
Dees_Troy43d8b002012-09-17 16:00:01 -0400195 unsigned long long dusize = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500196 unsigned long long dutemp = 0;
Dees_Troy43d8b002012-09-17 16:00:01 -0400197
Vojtech Bocek2e97ec52013-02-02 13:22:42 +0100198 d = opendir(Path.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400199 if (d == NULL)
200 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000201 LOGERR("error opening '%s'\n", Path.c_str());
202 LOGERR("error: %s\n", strerror(errno));
Dees_Troy43d8b002012-09-17 16:00:01 -0400203 return 0;
204 }
205
206 while ((de = readdir(d)) != NULL)
207 {
bigbiff bigbiff616afed2013-07-11 18:50:29 -0400208 if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0 && strcmp(de->d_name, "lost+found") != 0)
Dees_Troy43d8b002012-09-17 16:00:01 -0400209 {
Vojtech Bocek2e97ec52013-02-02 13:22:42 +0100210 dutemp = Get_Folder_Size((Path + "/" + de->d_name), Display_Error);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500211 dusize += dutemp;
212 dutemp = 0;
Dees_Troy43d8b002012-09-17 16:00:01 -0400213 }
214 else if (de->d_type == DT_REG)
215 {
Vojtech Bocek2e97ec52013-02-02 13:22:42 +0100216 stat((Path + "/" + de->d_name).c_str(), &st);
Dees_Troy43d8b002012-09-17 16:00:01 -0400217 dusize += (unsigned long long)(st.st_size);
218 }
219 }
220 closedir(d);
Dees_Troy43d8b002012-09-17 16:00:01 -0400221 return dusize;
222}
223
224bool TWFunc::Path_Exists(string Path) {
225 // Check to see if the Path exists
Dees_Troy7c2dec82012-09-26 09:49:14 -0400226 struct stat st;
Dees_Troy7c2dec82012-09-26 09:49:14 -0400227 if (stat(Path.c_str(), &st) != 0)
Dees_Troy43d8b002012-09-17 16:00:01 -0400228 return false;
229 else
230 return true;
Dees_Troyb46a6842012-09-25 11:06:46 -0400231}
232
233void TWFunc::GUI_Operation_Text(string Read_Value, string Default_Text) {
234 string Display_Text;
235
236 DataManager::GetValue(Read_Value, Display_Text);
237 if (Display_Text.empty())
238 Display_Text = Default_Text;
239
240 DataManager::SetValue("tw_operation", Display_Text);
241 DataManager::SetValue("tw_partition", "");
242}
243
244void TWFunc::GUI_Operation_Text(string Read_Value, string Partition_Name, string Default_Text) {
245 string Display_Text;
246
247 DataManager::GetValue(Read_Value, Display_Text);
248 if (Display_Text.empty())
249 Display_Text = Default_Text;
250
251 DataManager::SetValue("tw_operation", Display_Text);
252 DataManager::SetValue("tw_partition", Partition_Name);
Dees_Troy7c2dec82012-09-26 09:49:14 -0400253}
254
255unsigned long TWFunc::Get_File_Size(string Path) {
256 struct stat st;
257
258 if (stat(Path.c_str(), &st) != 0)
259 return 0;
260 return st.st_size;
Dees_Troya58bead2012-09-27 09:49:29 -0400261}
262
Dees_Troy2673cec2013-04-02 20:22:16 +0000263void TWFunc::Copy_Log(string Source, string Destination) {
264 FILE *destination_log = fopen(Destination.c_str(), "a");
265 if (destination_log == NULL) {
266 LOGERR("TWFunc::Copy_Log -- Can't open destination log file: '%s'\n", Destination.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600267 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000268 FILE *source_log = fopen(Source.c_str(), "r");
269 if (source_log != NULL) {
270 fseek(source_log, Log_Offset, SEEK_SET);
271 char buffer[4096];
272 while (fgets(buffer, sizeof(buffer), source_log))
273 fputs(buffer, destination_log); // Buffered write of log file
274 Log_Offset = ftell(source_log);
275 fflush(source_log);
276 fclose(source_log);
Dees_Troy6ef66352013-02-21 08:26:57 -0600277 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000278 fflush(destination_log);
279 fclose(destination_log);
Dees_Troy6ef66352013-02-21 08:26:57 -0600280 }
Dees_Troya58bead2012-09-27 09:49:29 -0400281}
282
Dees_Troy2673cec2013-04-02 20:22:16 +0000283void TWFunc::Update_Log_File(void) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500284 // Copy logs to cache so the system can find out what happened.
Dees_Troy2673cec2013-04-02 20:22:16 +0000285 Copy_Log(TMP_LOG_FILE, "/cache/recovery/log");
286 copy_file("/cache/recovery/log", "/cache/recovery/last_log", 600);
287 chown("/cache/recovery/log", 1000, 1000);
288 chmod("/cache/recovery/log", 0600);
289 chmod("/cache/recovery/last_log", 0640);
Dees_Troya58bead2012-09-27 09:49:29 -0400290
Dees_Troy2673cec2013-04-02 20:22:16 +0000291 // Reset bootloader message
292 TWPartition* Part = PartitionManager.Find_Partition_By_Path("/misc");
293 if (Part != NULL) {
294 struct bootloader_message boot;
295 memset(&boot, 0, sizeof(boot));
296 if (Part->Current_File_System == "mtd") {
297 if (set_bootloader_message_mtd_name(&boot, Part->MTD_Name.c_str()) != 0)
298 LOGERR("Unable to set MTD bootloader message.\n");
299 } else if (Part->Current_File_System == "emmc") {
300 if (set_bootloader_message_block_name(&boot, Part->Actual_Block_Device.c_str()) != 0)
301 LOGERR("Unable to set emmc bootloader message.\n");
302 } else {
303 LOGERR("Unknown file system for /misc: '%s'\n", Part->Current_File_System.c_str());
304 }
305 }
Dees_Troya58bead2012-09-27 09:49:29 -0400306
Dees_Troy2673cec2013-04-02 20:22:16 +0000307 if (!PartitionManager.Mount_By_Path("/cache", true) || (unlink("/cache/recovery/command") && errno != ENOENT)) {
308 LOGINFO("Can't unlink %s\n", "/cache/recovery/command");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500309 }
Dees_Troya58bead2012-09-27 09:49:29 -0400310
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500311 PartitionManager.UnMount_By_Path("/cache", true);
Dees_Troy2673cec2013-04-02 20:22:16 +0000312 sync();
313}
314
315void TWFunc::Update_Intent_File(string Intent) {
316 if (PartitionManager.Mount_By_Path("/cache", false) && !Intent.empty()) {
317 TWFunc::write_file("/cache/recovery/intent", Intent);
318 }
Dees_Troya58bead2012-09-27 09:49:29 -0400319}
320
321// reboot: Reboot the system. Return -1 on error, no return on success
322int TWFunc::tw_reboot(RebootCommand command)
323{
324 // Always force a sync before we reboot
Dees_Troy6ef66352013-02-21 08:26:57 -0600325 sync();
Dees_Troya58bead2012-09-27 09:49:29 -0400326
Dees_Troy2673cec2013-04-02 20:22:16 +0000327 switch (command) {
328 case rb_current:
329 case rb_system:
330 Update_Log_File();
331 Update_Intent_File("s");
332 sync();
333 check_and_run_script("/sbin/rebootsystem.sh", "reboot system");
334 return reboot(RB_AUTOBOOT);
335 case rb_recovery:
336 check_and_run_script("/sbin/rebootrecovery.sh", "reboot recovery");
337 return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "recovery");
338 case rb_bootloader:
339 check_and_run_script("/sbin/rebootbootloader.sh", "reboot bootloader");
340 return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "bootloader");
341 case rb_poweroff:
342 check_and_run_script("/sbin/poweroff.sh", "power off");
Dees_Troya4438782013-02-22 18:44:00 +0000343#ifdef ANDROID_RB_POWEROFF
Dees_Troy2673cec2013-04-02 20:22:16 +0000344 android_reboot(ANDROID_RB_POWEROFF, 0, 0);
Dees_Troya4438782013-02-22 18:44:00 +0000345#endif
Dees_Troy2673cec2013-04-02 20:22:16 +0000346 return reboot(RB_POWER_OFF);
347 case rb_download:
348 check_and_run_script("/sbin/rebootdownload.sh", "reboot download");
349 return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (void*) "download");
350 default:
351 return -1;
Dees_Troy6ef66352013-02-21 08:26:57 -0600352 }
353 return -1;
Dees_Troya58bead2012-09-27 09:49:29 -0400354}
355
356void TWFunc::check_and_run_script(const char* script_file, const char* display_name)
357{
358 // Check for and run startup script if script exists
359 struct stat st;
360 if (stat(script_file, &st) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000361 gui_print("Running %s script...\n", display_name);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500362 chmod(script_file, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
Vojtech Bocek05534202013-09-11 08:11:56 +0200363 TWFunc::Exec_Cmd(script_file);
Dees_Troy2673cec2013-04-02 20:22:16 +0000364 gui_print("\nFinished running %s script.\n", display_name);
Dees_Troya58bead2012-09-27 09:49:29 -0400365 }
Dees_Troy3477d712012-09-27 15:44:01 -0400366}
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500367
368int TWFunc::removeDir(const string path, bool skipParent) {
Dees_Troyce675462013-01-09 19:48:21 +0000369 DIR *d = opendir(path.c_str());
370 int r = 0;
371 string new_path;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500372
Dees_Troyce675462013-01-09 19:48:21 +0000373 if (d == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000374 LOGERR("Error opening '%s'\n", path.c_str());
Dees_Troyce675462013-01-09 19:48:21 +0000375 return -1;
376 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500377
Dees_Troyce675462013-01-09 19:48:21 +0000378 if (d) {
379 struct dirent *p;
380 while (!r && (p = readdir(d))) {
Dees_Troyce675462013-01-09 19:48:21 +0000381 if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
382 continue;
383 new_path = path + "/";
384 new_path.append(p->d_name);
385 if (p->d_type == DT_DIR) {
386 r = removeDir(new_path, true);
387 if (!r) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500388 if (p->d_type == DT_DIR)
389 r = rmdir(new_path.c_str());
390 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000391 LOGINFO("Unable to removeDir '%s': %s\n", new_path.c_str(), strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500392 }
bigbiff bigbiff98f1f902013-01-19 18:46:13 -0500393 } else if (p->d_type == DT_REG || p->d_type == DT_LNK || p->d_type == DT_FIFO || p->d_type == DT_SOCK) {
Dees_Troyce675462013-01-09 19:48:21 +0000394 r = unlink(new_path.c_str());
Dees_Troye34c1332013-02-06 19:13:00 +0000395 if (r != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000396 LOGINFO("Unable to unlink '%s: %s'\n", new_path.c_str(), strerror(errno));
Dees_Troye34c1332013-02-06 19:13:00 +0000397 }
Dees_Troyce675462013-01-09 19:48:21 +0000398 }
399 }
400 closedir(d);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500401
402 if (!r) {
403 if (skipParent)
404 return 0;
405 else
406 r = rmdir(path.c_str());
407 }
Dees_Troyce675462013-01-09 19:48:21 +0000408 }
409 return r;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500410}
411
412int TWFunc::copy_file(string src, string dst, int mode) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000413 LOGINFO("Copying file %s to %s\n", src.c_str(), dst.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500414 ifstream srcfile(src.c_str(), ios::binary);
415 ofstream dstfile(dst.c_str(), ios::binary);
416 dstfile << srcfile.rdbuf();
417 srcfile.close();
418 dstfile.close();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500419 if (chmod(dst.c_str(), mode) != 0)
420 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500421 return 0;
422}
Dees_Troy3ee47bc2013-01-25 21:47:37 +0000423
424unsigned int TWFunc::Get_D_Type_From_Stat(string Path) {
425 struct stat st;
426
427 stat(Path.c_str(), &st);
428 if (st.st_mode & S_IFDIR)
429 return DT_DIR;
430 else if (st.st_mode & S_IFBLK)
431 return DT_BLK;
432 else if (st.st_mode & S_IFCHR)
433 return DT_CHR;
434 else if (st.st_mode & S_IFIFO)
435 return DT_FIFO;
436 else if (st.st_mode & S_IFLNK)
437 return DT_LNK;
438 else if (st.st_mode & S_IFREG)
439 return DT_REG;
440 else if (st.st_mode & S_IFSOCK)
441 return DT_SOCK;
442 return DT_UNKNOWN;
Dees_Troye34c1332013-02-06 19:13:00 +0000443}
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500444
445int TWFunc::read_file(string fn, string& results) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200446 ifstream file;
447 file.open(fn.c_str(), ios::in);
448
449 if (file.is_open()) {
450 file >> results;
451 file.close();
452 return 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500453 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200454
455 LOGINFO("Cannot find file %s\n", fn.c_str());
456 return -1;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500457}
458
459int TWFunc::read_file(string fn, vector<string>& results) {
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500460 ifstream file;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500461 string line;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500462 file.open(fn.c_str(), ios::in);
463 if (file.is_open()) {
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500464 while (getline(file, line))
465 results.push_back(line);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500466 file.close();
467 return 0;
468 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000469 LOGINFO("Cannot find file %s\n", fn.c_str());
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500470 return -1;
471}
472
473int TWFunc::write_file(string fn, string& line) {
474 FILE *file;
475 file = fopen(fn.c_str(), "w");
476 if (file != NULL) {
477 fwrite(line.c_str(), line.size(), 1, file);
478 fclose(file);
479 return 0;
480 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000481 LOGINFO("Cannot find file %s\n", fn.c_str());
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500482 return -1;
483}
484
Dees_Troy83bd4832013-05-04 12:39:56 +0000485vector<string> TWFunc::split_string(const string &in, char del, bool skip_empty) {
486 vector<string> res;
487
488 if (in.empty() || del == '\0')
489 return res;
490
491 string field;
492 istringstream f(in);
493 if (del == '\n') {
494 while(getline(f, field)) {
495 if (field.empty() && skip_empty)
496 continue;
497 res.push_back(field);
498 }
499 } else {
500 while(getline(f, field, del)) {
501 if (field.empty() && skip_empty)
502 continue;
503 res.push_back(field);
504 }
505 }
506 return res;
507}
508
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500509timespec TWFunc::timespec_diff(timespec& start, timespec& end)
510{
Dees_Troy6ef66352013-02-21 08:26:57 -0600511 timespec temp;
512 if ((end.tv_nsec-start.tv_nsec)<0) {
513 temp.tv_sec = end.tv_sec-start.tv_sec-1;
514 temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
515 } else {
516 temp.tv_sec = end.tv_sec-start.tv_sec;
517 temp.tv_nsec = end.tv_nsec-start.tv_nsec;
518 }
519 return temp;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500520}
521
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200522int TWFunc::drop_caches(void) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600523 string file = "/proc/sys/vm/drop_caches";
524 string value = "3";
525 if (write_file(file, value) != 0)
526 return -1;
527 return 0;
528}
529
530int TWFunc::Check_su_Perms(void) {
531 struct stat st;
532 int ret = 0;
533
534 if (!PartitionManager.Mount_By_Path("/system", false))
535 return 0;
536
537 // Check to ensure that perms are 6755 for all 3 file locations
538 if (stat("/system/bin/su", &st) == 0) {
539 if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) {
540 ret = 1;
541 }
542 }
543 if (stat("/system/xbin/su", &st) == 0) {
544 if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) {
545 ret += 2;
546 }
547 }
548 if (stat("/system/bin/.ext/.su", &st) == 0) {
549 if ((st.st_mode & (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != (S_ISUID | S_ISGID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) || st.st_uid != 0 || st.st_gid != 0) {
550 ret += 4;
551 }
552 }
553 return ret;
554}
555
556bool TWFunc::Fix_su_Perms(void) {
557 if (!PartitionManager.Mount_By_Path("/system", true))
558 return false;
559
560 string file = "/system/bin/su";
561 if (TWFunc::Path_Exists(file)) {
562 if (chown(file.c_str(), 0, 0) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000563 LOGERR("Failed to chown '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600564 return false;
565 }
566 if (tw_chmod(file, "6755") != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000567 LOGERR("Failed to chmod '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600568 return false;
569 }
570 }
571 file = "/system/xbin/su";
572 if (TWFunc::Path_Exists(file)) {
573 if (chown(file.c_str(), 0, 0) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000574 LOGERR("Failed to chown '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600575 return false;
576 }
577 if (tw_chmod(file, "6755") != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000578 LOGERR("Failed to chmod '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600579 return false;
580 }
581 }
Dees_Troya7939bb2013-08-29 20:21:12 +0000582 file = "/system/xbin/daemonsu";
583 if (TWFunc::Path_Exists(file)) {
584 if (chown(file.c_str(), 0, 0) != 0) {
585 LOGERR("Failed to chown '%s'\n", file.c_str());
586 return false;
587 }
588 if (tw_chmod(file, "6755") != 0) {
589 LOGERR("Failed to chmod '%s'\n", file.c_str());
590 return false;
591 }
592 }
Dees_Troy6ef66352013-02-21 08:26:57 -0600593 file = "/system/bin/.ext/.su";
594 if (TWFunc::Path_Exists(file)) {
595 if (chown(file.c_str(), 0, 0) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000596 LOGERR("Failed to chown '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600597 return false;
598 }
599 if (tw_chmod(file, "6755") != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000600 LOGERR("Failed to chmod '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600601 return false;
602 }
603 }
Dees_Troya7939bb2013-08-29 20:21:12 +0000604 file = "/system/etc/install-recovery.sh";
605 if (TWFunc::Path_Exists(file)) {
606 if (chown(file.c_str(), 0, 0) != 0) {
607 LOGERR("Failed to chown '%s'\n", file.c_str());
608 return false;
609 }
610 if (tw_chmod(file, "0755") != 0) {
611 LOGERR("Failed to chmod '%s'\n", file.c_str());
612 return false;
613 }
614 }
615 file = "/system/etc/init.d/99SuperSUDaemon";
616 if (TWFunc::Path_Exists(file)) {
617 if (chown(file.c_str(), 0, 0) != 0) {
618 LOGERR("Failed to chown '%s'\n", file.c_str());
619 return false;
620 }
621 if (tw_chmod(file, "0755") != 0) {
622 LOGERR("Failed to chmod '%s'\n", file.c_str());
623 return false;
624 }
625 }
Dees_Troy6ef66352013-02-21 08:26:57 -0600626 file = "/system/app/Superuser.apk";
627 if (TWFunc::Path_Exists(file)) {
628 if (chown(file.c_str(), 0, 0) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000629 LOGERR("Failed to chown '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600630 return false;
631 }
632 if (tw_chmod(file, "0644") != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000633 LOGERR("Failed to chmod '%s'\n", file.c_str());
Dees_Troy6ef66352013-02-21 08:26:57 -0600634 return false;
635 }
636 }
637 sync();
638 if (!PartitionManager.UnMount_By_Path("/system", true))
639 return false;
640 return true;
641}
642
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200643int TWFunc::tw_chmod(const string& fn, const string& mode) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600644 long mask = 0;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200645 std::string::size_type n = mode.length();
646 int cls = 0;
Dees_Troy6ef66352013-02-21 08:26:57 -0600647
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200648 if(n == 3)
649 ++cls;
650 else if(n != 4)
651 {
652 LOGERR("TWFunc::tw_chmod used with %u long mode string (should be 3 or 4)!\n", mode.length());
653 return -1;
654 }
655
656 for (n = 0; n < mode.length(); ++n, ++cls) {
657 if (cls == 0) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600658 if (mode[n] == '0')
659 continue;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200660 else if (mode[n] == '1')
Dees_Troy6ef66352013-02-21 08:26:57 -0600661 mask |= S_ISVTX;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200662 else if (mode[n] == '2')
Dees_Troy6ef66352013-02-21 08:26:57 -0600663 mask |= S_ISGID;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200664 else if (mode[n] == '4')
Dees_Troy6ef66352013-02-21 08:26:57 -0600665 mask |= S_ISUID;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200666 else if (mode[n] == '5') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600667 mask |= S_ISVTX;
668 mask |= S_ISUID;
669 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200670 else if (mode[n] == '6') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600671 mask |= S_ISGID;
672 mask |= S_ISUID;
673 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200674 else if (mode[n] == '7') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600675 mask |= S_ISVTX;
676 mask |= S_ISGID;
677 mask |= S_ISUID;
678 }
679 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200680 else if (cls == 1) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600681 if (mode[n] == '7') {
682 mask |= S_IRWXU;
683 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200684 else if (mode[n] == '6') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600685 mask |= S_IRUSR;
686 mask |= S_IWUSR;
687 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200688 else if (mode[n] == '5') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600689 mask |= S_IRUSR;
690 mask |= S_IXUSR;
691 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200692 else if (mode[n] == '4')
Dees_Troy6ef66352013-02-21 08:26:57 -0600693 mask |= S_IRUSR;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200694 else if (mode[n] == '3') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600695 mask |= S_IWUSR;
696 mask |= S_IRUSR;
697 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200698 else if (mode[n] == '2')
Dees_Troy6ef66352013-02-21 08:26:57 -0600699 mask |= S_IWUSR;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200700 else if (mode[n] == '1')
Dees_Troy6ef66352013-02-21 08:26:57 -0600701 mask |= S_IXUSR;
702 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200703 else if (cls == 2) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600704 if (mode[n] == '7') {
705 mask |= S_IRWXG;
706 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200707 else if (mode[n] == '6') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600708 mask |= S_IRGRP;
709 mask |= S_IWGRP;
710 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200711 else if (mode[n] == '5') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600712 mask |= S_IRGRP;
713 mask |= S_IXGRP;
714 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200715 else if (mode[n] == '4')
Dees_Troy6ef66352013-02-21 08:26:57 -0600716 mask |= S_IRGRP;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200717 else if (mode[n] == '3') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600718 mask |= S_IWGRP;
719 mask |= S_IXGRP;
720 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200721 else if (mode[n] == '2')
Dees_Troy6ef66352013-02-21 08:26:57 -0600722 mask |= S_IWGRP;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200723 else if (mode[n] == '1')
Dees_Troy6ef66352013-02-21 08:26:57 -0600724 mask |= S_IXGRP;
725 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200726 else if (cls == 3) {
Dees_Troy6ef66352013-02-21 08:26:57 -0600727 if (mode[n] == '7') {
728 mask |= S_IRWXO;
729 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200730 else if (mode[n] == '6') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600731 mask |= S_IROTH;
732 mask |= S_IWOTH;
733 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200734 else if (mode[n] == '5') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600735 mask |= S_IROTH;
736 mask |= S_IXOTH;
737 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200738 else if (mode[n] == '4')
739 mask |= S_IROTH;
740 else if (mode[n] == '3') {
Dees_Troy6ef66352013-02-21 08:26:57 -0600741 mask |= S_IWOTH;
742 mask |= S_IXOTH;
743 }
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200744 else if (mode[n] == '2')
Dees_Troy6ef66352013-02-21 08:26:57 -0600745 mask |= S_IWOTH;
Vojtech Bocek37aeb8d2013-08-29 22:38:20 +0200746 else if (mode[n] == '1')
Dees_Troy6ef66352013-02-21 08:26:57 -0600747 mask |= S_IXOTH;
748 }
749 }
750
751 if (chmod(fn.c_str(), mask) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000752 LOGERR("Unable to chmod '%s' %l\n", fn.c_str(), mask);
Dees_Troy6ef66352013-02-21 08:26:57 -0600753 return -1;
754 }
755
756 return 0;
757}
758
759bool TWFunc::Install_SuperSU(void) {
760 if (!PartitionManager.Mount_By_Path("/system", true))
761 return false;
762
Vojtech Bocek05534202013-09-11 08:11:56 +0200763 TWFunc::Exec_Cmd("/sbin/chattr -i /system/xbin/su");
jt1134113ee732013-02-22 23:26:10 -0600764 if (copy_file("/supersu/su", "/system/xbin/su", 0755) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000765 LOGERR("Failed to copy su binary to /system/bin\n");
Dees_Troy6ef66352013-02-21 08:26:57 -0600766 return false;
767 }
Dees_Troya7939bb2013-08-29 20:21:12 +0000768 if (!Path_Exists("/system/bin/.ext")) {
769 mkdir("/system/bin/.ext", 0777);
770 }
Vojtech Bocek05534202013-09-11 08:11:56 +0200771 TWFunc::Exec_Cmd("/sbin/chattr -i /system/bin/.ext/su");
Dees_Troya7939bb2013-08-29 20:21:12 +0000772 if (copy_file("/supersu/su", "/system/bin/.ext/su", 0755) != 0) {
773 LOGERR("Failed to copy su binary to /system/bin/.ext/su\n");
774 return false;
775 }
Vojtech Bocek05534202013-09-11 08:11:56 +0200776 TWFunc::Exec_Cmd("/sbin/chattr -i /system/xbin/daemonsu");
Dees_Troya7939bb2013-08-29 20:21:12 +0000777 if (copy_file("/supersu/su", "/system/xbin/daemonsu", 0755) != 0) {
778 LOGERR("Failed to copy su binary to /system/xbin/daemonsu\n");
779 return false;
780 }
781 if (Path_Exists("/system/etc/init.d")) {
Vojtech Bocek05534202013-09-11 08:11:56 +0200782 TWFunc::Exec_Cmd("/sbin/chattr -i /system/etc/init.d/99SuperSUDaemon");
Dees_Troya7939bb2013-08-29 20:21:12 +0000783 if (copy_file("/supersu/99SuperSUDaemon", "/system/etc/init.d/99SuperSUDaemon", 0755) != 0) {
784 LOGERR("Failed to copy 99SuperSUDaemon to /system/etc/init.d/99SuperSUDaemon\n");
785 return false;
786 }
787 } else {
Vojtech Bocek05534202013-09-11 08:11:56 +0200788 TWFunc::Exec_Cmd("/sbin/chattr -i /system/etc/install-recovery.sh");
Dees_Troya7939bb2013-08-29 20:21:12 +0000789 if (copy_file("/supersu/install-recovery.sh", "/system/etc/install-recovery.sh", 0755) != 0) {
790 LOGERR("Failed to copy install-recovery.sh to /system/etc/install-recovery.sh\n");
791 return false;
792 }
793 }
jt1134113ee732013-02-22 23:26:10 -0600794 if (copy_file("/supersu/Superuser.apk", "/system/app/Superuser.apk", 0644) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000795 LOGERR("Failed to copy Superuser app to /system/app\n");
Dees_Troy6ef66352013-02-21 08:26:57 -0600796 return false;
797 }
798 if (!Fix_su_Perms())
799 return false;
800 return true;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500801}
Dees_Troy83bd4832013-05-04 12:39:56 +0000802
803int TWFunc::Get_File_Type(string fn) {
804 string::size_type i = 0;
805 int firstbyte = 0, secondbyte = 0;
806 char header[3];
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200807
Dees_Troy83bd4832013-05-04 12:39:56 +0000808 ifstream f;
809 f.open(fn.c_str(), ios::in | ios::binary);
810 f.get(header, 3);
811 f.close();
812 firstbyte = header[i] & 0xff;
813 secondbyte = header[++i] & 0xff;
814
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200815 if (firstbyte == 0x1f && secondbyte == 0x8b)
Dees_Troy83bd4832013-05-04 12:39:56 +0000816 return 1; // Compressed
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200817 else if (firstbyte == 0x4f && secondbyte == 0x41)
Dees_Troy83bd4832013-05-04 12:39:56 +0000818 return 2; // Encrypted
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200819 else
Dees_Troy83bd4832013-05-04 12:39:56 +0000820 return 0; // Unknown
Dees_Troy83bd4832013-05-04 12:39:56 +0000821
822 return 0;
823}
824
825int TWFunc::Try_Decrypting_File(string fn, string password) {
826#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
827 OAES_CTX * ctx = NULL;
828 uint8_t _key_data[32] = "";
829 FILE *f;
830 uint8_t buffer[4096];
831 uint8_t *buffer_out = NULL;
832 uint8_t *ptr = NULL;
833 size_t read_len = 0, out_len = 0;
834 int firstbyte = 0, secondbyte = 0, key_len;
835 size_t _j = 0;
836 size_t _key_data_len = 0;
837
838 // mostly kanged from OpenAES oaes.c
839 for( _j = 0; _j < 32; _j++ )
840 _key_data[_j] = _j + 1;
841 _key_data_len = password.size();
842 if( 16 >= _key_data_len )
843 _key_data_len = 16;
844 else if( 24 >= _key_data_len )
845 _key_data_len = 24;
846 else
847 _key_data_len = 32;
848 memcpy(_key_data, password.c_str(), password.size());
849
850 ctx = oaes_alloc();
851 if (ctx == NULL) {
852 LOGERR("Failed to allocate OAES\n");
853 return -1;
854 }
855
856 oaes_key_import_data(ctx, _key_data, _key_data_len);
857
858 f = fopen(fn.c_str(), "rb");
859 if (f == NULL) {
860 LOGERR("Failed to open '%s' to try decrypt\n", fn.c_str());
861 return -1;
862 }
863 read_len = fread(buffer, sizeof(uint8_t), 4096, f);
864 if (read_len <= 0) {
865 LOGERR("Read size during try decrypt failed\n");
866 fclose(f);
867 return -1;
868 }
869 if (oaes_decrypt(ctx, buffer, read_len, NULL, &out_len) != OAES_RET_SUCCESS) {
870 LOGERR("Error: Failed to retrieve required buffer size for trying decryption.\n");
871 fclose(f);
872 return -1;
873 }
874 buffer_out = (uint8_t *) calloc(out_len, sizeof(char));
875 if (buffer_out == NULL) {
876 LOGERR("Failed to allocate output buffer for try decrypt.\n");
877 fclose(f);
878 return -1;
879 }
880 if (oaes_decrypt(ctx, buffer, read_len, buffer_out, &out_len) != OAES_RET_SUCCESS) {
881 LOGERR("Failed to decrypt file '%s'\n", fn.c_str());
882 fclose(f);
883 free(buffer_out);
884 return 0;
885 }
886 fclose(f);
887 if (out_len < 2) {
888 LOGINFO("Successfully decrypted '%s' but read length %i too small.\n", fn.c_str(), out_len);
889 free(buffer_out);
890 return 1; // Decrypted successfully
891 }
892 ptr = buffer_out;
893 firstbyte = *ptr & 0xff;
894 ptr++;
895 secondbyte = *ptr & 0xff;
896 if (firstbyte == 0x1f && secondbyte == 0x8b) {
897 LOGINFO("Successfully decrypted '%s' and file is compressed.\n", fn.c_str());
898 free(buffer_out);
899 return 3; // Compressed
900 }
901 if (out_len >= 262) {
902 ptr = buffer_out + 257;
903 if (strncmp((char*)ptr, "ustar", 5) == 0) {
904 LOGINFO("Successfully decrypted '%s' and file is tar format.\n", fn.c_str());
905 free(buffer_out);
906 return 2; // Tar
907 }
908 }
909 free(buffer_out);
910 LOGINFO("No errors decrypting '%s' but no known file format.\n", fn.c_str());
911 return 1; // Decrypted successfully
912#else
913 LOGERR("Encrypted backup support not included.\n");
914 return -1;
915#endif
916}
917
918bool TWFunc::Try_Decrypting_Backup(string Restore_Path, string Password) {
919 DIR* d;
920
921 string Filename;
922 Restore_Path += "/";
923 d = opendir(Restore_Path.c_str());
924 if (d == NULL) {
925 LOGERR("Error opening '%s'\n", Restore_Path.c_str());
926 return false;
927 }
928
929 struct dirent* de;
930 while ((de = readdir(d)) != NULL) {
931 Filename = Restore_Path;
932 Filename += de->d_name;
933 if (TWFunc::Get_File_Type(Filename) == 2) {
934 if (TWFunc::Try_Decrypting_File(Filename, Password) < 2) {
935 DataManager::SetValue("tw_restore_password", ""); // Clear the bad password
936 DataManager::SetValue("tw_restore_display", ""); // Also clear the display mask
937 closedir(d);
938 return false;
939 }
940 }
941 }
942 closedir(d);
943 return true;
944}
945
946int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) {
947 pid_t rc_pid;
948
949 rc_pid = waitpid(pid, status, 0);
950 if (rc_pid > 0) {
951 if (WEXITSTATUS(*status) == 0)
952 LOGINFO("%s process ended with RC=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Success
953 else if (WIFSIGNALED(*status)) {
954 LOGINFO("%s process ended with signal: %d\n", Child_Name.c_str(), WTERMSIG(*status)); // Seg fault or some other non-graceful termination
955 return -1;
956 } else if (WEXITSTATUS(*status) != 0) {
957 LOGINFO("%s process ended with ERROR=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Graceful exit, but there was an error
958 return -1;
959 }
960 } else { // no PID returned
961 if (errno == ECHILD)
962 LOGINFO("%s no child process exist\n", Child_Name.c_str());
963 else {
964 LOGINFO("%s Unexpected error\n", Child_Name.c_str());
965 return -1;
966 }
967 }
968 return 0;
969}
Dees Troyb21cc642013-09-10 17:36:41 +0000970
971string TWFunc::Get_Current_Date() {
972 string Current_Date;
973 time_t seconds = time(0);
974 struct tm *t = localtime(&seconds);
975 char timestamp[255];
976 sprintf(timestamp,"%04d-%02d-%02d--%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
977 Current_Date = timestamp;
978 return Current_Date;
979}
980
981void TWFunc::Auto_Generate_Backup_Name() {
982 bool mount_state = PartitionManager.Is_Mounted_By_Path("/system");
983 std::vector<string> buildprop;
984 if (!PartitionManager.Mount_By_Path("/system", true)) {
985 DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date());
986 return;
987 }
988 if (TWFunc::read_file("/system/build.prop", buildprop) != 0) {
989 LOGINFO("Unable to open /system/build.prop for getting backup name.\n");
990 DataManager::SetValue(TW_BACKUP_NAME, "");
991 if (!mount_state)
992 PartitionManager.UnMount_By_Path("/system", false);
993 return;
994 }
995 int line_count = buildprop.size();
996 int index;
997 size_t start_pos = 0, end_pos;
998 string propname, propvalue;
999 for (index = 0; index < line_count; index++) {
1000 end_pos = buildprop.at(index).find("=", start_pos);
1001 propname = buildprop.at(index).substr(start_pos, end_pos);
1002 if (propname == "ro.build.display.id") {
1003 propvalue = buildprop.at(index).substr(end_pos + 1, buildprop.at(index).size());
1004 string Backup_Name = Get_Current_Date();
1005 Backup_Name += " " + propvalue;
1006 if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
1007 Backup_Name.resize(MAX_BACKUP_NAME_LEN);
1008 DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
1009 break;
1010 }
1011 }
1012 if (propvalue.empty()) {
1013 LOGINFO("ro.build.display.id not found in build.prop\n");
1014 }
1015 if (!mount_state)
1016 PartitionManager.UnMount_By_Path("/system", false);
Vojtech Bocek05534202013-09-11 08:11:56 +02001017}