diff options
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | libtar/Android.mk | 20 | ||||
-rw-r--r-- | libtar/append.c | 3 | ||||
-rw-r--r-- | openaes/Android.mk | 13 | ||||
-rw-r--r-- | openrecoveryscript.cpp | 4 | ||||
-rw-r--r-- | partition.cpp | 61 | ||||
-rwxr-xr-x | prebuilt/install-recovery.sh | 10 | ||||
-rwxr-xr-x | prebuilt/su | bin | 112164 -> 113036 bytes | |||
-rw-r--r-- | twcommon.h | 6 | ||||
-rw-r--r-- | twrp-functions.cpp | 426 | ||||
-rw-r--r-- | twrp-functions.hpp | 21 | ||||
-rw-r--r-- | twrpTar.cpp | 55 | ||||
-rw-r--r-- | twrpTar.hpp | 3 | ||||
-rw-r--r-- | twrpTarMain/Android.mk | 71 | ||||
-rw-r--r-- | twrpTarMain/twrpTarMain.cpp | 164 |
15 files changed, 549 insertions, 311 deletions
diff --git a/Android.mk b/Android.mk index 4ab358a9d..c6c7f3c40 100644 --- a/Android.mk +++ b/Android.mk @@ -353,7 +353,8 @@ include $(commands_recovery_local_path)/injecttwrp/Android.mk \ $(commands_recovery_local_path)/minuitwrp/Android.mk \ $(commands_recovery_local_path)/openaes/Android.mk \ $(commands_recovery_local_path)/toolbox/Android.mk \ - $(commands_recovery_local_path)/libmincrypt/Android.mk + $(commands_recovery_local_path)/libmincrypt/Android.mk \ + $(commands_recovery_local_path)/twrpTarMain/Android.mk ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true) include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk diff --git a/libtar/Android.mk b/libtar/Android.mk index f936e96ff..1972573bb 100644 --- a/libtar/Android.mk +++ b/libtar/Android.mk @@ -1,5 +1,6 @@ LOCAL_PATH := $(call my-dir) +# Build shared library include $(CLEAR_VARS) LOCAL_MODULE := libtar @@ -19,3 +20,22 @@ endif include $(BUILD_SHARED_LIBRARY) +# Build static library +include $(CLEAR_VARS) + +LOCAL_MODULE := libtar_static +LOCAL_MODULE_TAGS := eng +LOCAL_MODULES_TAGS = optional +LOCAL_CFLAGS = +LOCAL_SRC_FILES = append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c +LOCAL_C_INCLUDES += $(LOCAL_PATH) \ + external/zlib +LOCAL_STATIC_LIBRARIES += libz libc + +ifeq ($(TWHAVE_SELINUX), true) + LOCAL_C_INCLUDES += external/libselinux/include + LOCAL_STATIC_LIBRARIES += libselinux + LOCAL_CFLAGS += -DHAVE_SELINUX +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/libtar/append.c b/libtar/append.c index dcd864984..514cf54bb 100644 --- a/libtar/append.c +++ b/libtar/append.c @@ -27,6 +27,9 @@ # include <unistd.h> #endif +#ifdef HAVE_SELINUX +#include "selinux/selinux.h" +#endif struct tar_dev { diff --git a/openaes/Android.mk b/openaes/Android.mk index 1beefdac4..360cf6ccc 100644 --- a/openaes/Android.mk +++ b/openaes/Android.mk @@ -2,6 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) ifneq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true) + # Build shared binary LOCAL_SRC_FILES:= src/oaes.c \ LOCAL_C_INCLUDES := \ bootable/recovery/openaes/src/isaac \ @@ -14,6 +15,7 @@ ifneq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true) LOCAL_SHARED_LIBRARIES = libopenaes libc include $(BUILD_EXECUTABLE) + # Build shared library include $(CLEAR_VARS) LOCAL_MODULE := libopenaes LOCAL_MODULE_TAGS := eng @@ -23,4 +25,15 @@ ifneq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true) LOCAL_SRC_FILES = src/oaes_lib.c src/isaac/rand.c LOCAL_SHARED_LIBRARIES = libc include $(BUILD_SHARED_LIBRARY) + + # Build static library + include $(CLEAR_VARS) + LOCAL_MODULE := libopenaes_static + LOCAL_MODULE_TAGS := eng + LOCAL_C_INCLUDES := \ + bootable/recovery/openaes/src/isaac \ + bootable/recovery/openaes/inc + LOCAL_SRC_FILES = src/oaes_lib.c src/isaac/rand.c + LOCAL_STATIC_LIBRARIES = libc + include $(BUILD_STATIC_LIBRARY) endif diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp index bede6d7c2..4479ec919 100644 --- a/openrecoveryscript.cpp +++ b/openrecoveryscript.cpp @@ -349,6 +349,10 @@ int OpenRecoveryScript::run_script_file(void) { sideload = 1; // Causes device to go to the home screen afterwards gui_print("Sideload finished.\n"); } + } else if (strcmp(command, "fixperms") == 0 || strcmp(command, "fixpermissions") == 0) { + ret_val = PartitionManager.Fix_Permissions(); + if (ret_val != 0) + ret_val = 1; // failure } else { LOGERR("Unrecognized script command: '%s'\n", command); ret_val = 1; diff --git a/partition.cpp b/partition.cpp index 3f19b7d61..74271922f 100644 --- a/partition.cpp +++ b/partition.cpp @@ -53,6 +53,7 @@ extern "C" { } #ifdef HAVE_SELINUX #include "selinux/selinux.h" +#include <selinux/label.h> #endif using namespace std; @@ -1344,17 +1345,25 @@ bool TWPartition::Wipe_EXT4() { return false; #if defined(HAVE_SELINUX) && defined(USE_EXT4) + int ret; + char *secontext = NULL; + gui_print("Formatting %s using make_ext4fs function.\n", Display_Name.c_str()); - if (make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle) != 0) { + + if (selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) { + LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str()); + ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL); + } else { + ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle); + } + if (ret != 0) { LOGERR("Unable to wipe '%s' using function call.\n", Mount_Point.c_str()); return false; } else { - #ifdef HAVE_SELINUX string sedir = Mount_Point + "/lost+found"; PartitionManager.Mount_By_Path(sedir.c_str(), true); rmdir(sedir.c_str()); mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP); - #endif return true; } #else @@ -1584,6 +1593,9 @@ bool TWPartition::Backup_Tar(string backup_folder) { tar.use_encryption = use_encryption; if (Use_Userdata_Encryption) tar.userdata_encryption = use_encryption; + string Password; + DataManager::GetValue("tw_backup_password", Password); + tar.setpassword(Password); } else { use_encryption = false; } @@ -1672,37 +1684,18 @@ bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System) return false; Full_FileName = restore_folder + "/" + Backup_FileName; - /*if (!TWFunc::Path_Exists(Full_FileName)) { - if (!TWFunc::Path_Exists(Full_FileName)) { - // Backup is multiple archives - LOGINFO("Backup is multiple archives.\n"); - sprintf(split_index, "%03i", index); - Full_FileName = restore_folder + "/" + Backup_FileName + split_index; - while (TWFunc::Path_Exists(Full_FileName)) { - index++; - gui_print("Restoring archive %i...\n", index); - LOGINFO("Restoring '%s'...\n", Full_FileName.c_str()); - twrpTar tar; - tar.setdir("/"); - tar.setfn(Full_FileName); - if (tar.extractTarFork() != 0) - return false; - sprintf(split_index, "%03i", index); - Full_FileName = restore_folder + "/" + Backup_FileName + split_index; - } - if (index == 0) { - LOGERR("Error locating restore file: '%s'\n", Full_FileName.c_str()); - return false; - } - } - } else {*/ - twrpTar tar; - tar.setdir(Backup_Path); - tar.setfn(Full_FileName); - tar.backup_name = Backup_Name; - if (tar.extractTarFork() != 0) - return false; - //} + twrpTar tar; + tar.setdir(Backup_Path); + tar.setfn(Full_FileName); + tar.backup_name = Backup_Name; +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + string Password; + DataManager::GetValue("tw_restore_password", Password); + if (!Password.empty()) + tar.setpassword(Password); +#endif + if (tar.extractTarFork() != 0) + return false; return true; } diff --git a/prebuilt/install-recovery.sh b/prebuilt/install-recovery.sh index 9b4374520..f62cf0b96 100755 --- a/prebuilt/install-recovery.sh +++ b/prebuilt/install-recovery.sh @@ -5,15 +5,13 @@ # to launch it from init.rc # Launches SuperSU in daemon mode only on Android 4.3+. -# Nothing will happen on 4.2.x or older. +# Nothing will happen on 4.2.x or older, unless SELinux+Enforcing. # If you want to force loading the daemon, use "--daemon" instead /system/xbin/daemonsu --auto-daemon & -# Some apps like to run stuff from this script as well, but the -# installer will have done "chattr +i" on this file to prevent -# accidental modification and deletion. In your code, just search -# this file for "install-recovery-2.sh", and if present, write -# there instead. +# Some apps like to run stuff from this script as well, that will +# obviously break root - in your code, just search this file +# for "install-recovery-2.sh", and if present, write there instead. /system/etc/install-recovery-2.sh diff --git a/prebuilt/su b/prebuilt/su Binary files differindex da77f0a70..941542798 100755 --- a/prebuilt/su +++ b/prebuilt/su diff --git a/twcommon.h b/twcommon.h index 2c96d04e2..69cc7e676 100644 --- a/twcommon.h +++ b/twcommon.h @@ -5,9 +5,15 @@ extern "C" { #endif +#ifndef BUILD_TWRPTAR_MAIN #include "gui/gui.h" #define LOGERR(...) gui_print("E:" __VA_ARGS__) #define LOGINFO(...) fprintf(stdout, "I:" __VA_ARGS__) +#else +#define LOGERR(...) printf("E:" __VA_ARGS__) +#define LOGINFO(...) printf("I:" __VA_ARGS__) +#define gui_print(...) printf( __VA_ARGS__ ) +#endif #define STRINGIFY(x) #x #define EXPAND(x) STRINGIFY(x) diff --git a/twrp-functions.cpp b/twrp-functions.cpp index df7174362..5145b2678 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -18,7 +18,7 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <string> #include <unistd.h> #include <vector> #include <dirent.h> @@ -32,18 +32,20 @@ #include <sys/vfs.h> #include <sys/types.h> #include <sys/wait.h> -#ifdef ANDROID_RB_POWEROFF - #include "cutils/android_reboot.h" -#endif #include <iostream> #include <fstream> #include <sstream> #include "twrp-functions.hpp" -#include "partitions.hpp" #include "twcommon.h" +#ifndef BUILD_TWRPTAR_MAIN #include "data.hpp" +#include "partitions.hpp" #include "variables.h" #include "bootloader.h" +#ifdef ANDROID_RB_POWEROFF + #include "cutils/android_reboot.h" +#endif +#endif // ndef BUILD_TWRPTAR_MAIN #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS #include "openaes/inc/oaes_lib.h" #endif @@ -115,6 +117,165 @@ string TWFunc::Get_Path(string Path) { return Path; } +int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) { + pid_t rc_pid; + + rc_pid = waitpid(pid, status, 0); + if (rc_pid > 0) { + if (WEXITSTATUS(*status) == 0) + LOGINFO("%s process ended with RC=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Success + else if (WIFSIGNALED(*status)) { + LOGINFO("%s process ended with signal: %d\n", Child_Name.c_str(), WTERMSIG(*status)); // Seg fault or some other non-graceful termination + return -1; + } else if (WEXITSTATUS(*status) != 0) { + LOGINFO("%s process ended with ERROR=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Graceful exit, but there was an error + return -1; + } + } else { // no PID returned + if (errno == ECHILD) + LOGINFO("%s no child process exist\n", Child_Name.c_str()); + else { + LOGINFO("%s Unexpected error\n", Child_Name.c_str()); + return -1; + } + } + return 0; +} + +bool TWFunc::Path_Exists(string Path) { + // Check to see if the Path exists + struct stat st; + if (stat(Path.c_str(), &st) != 0) + return false; + else + return true; +} + +int TWFunc::Get_File_Type(string fn) { + string::size_type i = 0; + int firstbyte = 0, secondbyte = 0; + char header[3]; + + ifstream f; + f.open(fn.c_str(), ios::in | ios::binary); + f.get(header, 3); + f.close(); + firstbyte = header[i] & 0xff; + secondbyte = header[++i] & 0xff; + + if (firstbyte == 0x1f && secondbyte == 0x8b) + return 1; // Compressed + else if (firstbyte == 0x4f && secondbyte == 0x41) + return 2; // Encrypted + else + return 0; // Unknown + + return 0; +} + +int TWFunc::Try_Decrypting_File(string fn, string password) { +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + OAES_CTX * ctx = NULL; + uint8_t _key_data[32] = ""; + FILE *f; + uint8_t buffer[4096]; + uint8_t *buffer_out = NULL; + uint8_t *ptr = NULL; + size_t read_len = 0, out_len = 0; + int firstbyte = 0, secondbyte = 0, key_len; + size_t _j = 0; + size_t _key_data_len = 0; + + // mostly kanged from OpenAES oaes.c + for( _j = 0; _j < 32; _j++ ) + _key_data[_j] = _j + 1; + _key_data_len = password.size(); + if( 16 >= _key_data_len ) + _key_data_len = 16; + else if( 24 >= _key_data_len ) + _key_data_len = 24; + else + _key_data_len = 32; + memcpy(_key_data, password.c_str(), password.size()); + + ctx = oaes_alloc(); + if (ctx == NULL) { + LOGERR("Failed to allocate OAES\n"); + return -1; + } + + oaes_key_import_data(ctx, _key_data, _key_data_len); + + f = fopen(fn.c_str(), "rb"); + if (f == NULL) { + LOGERR("Failed to open '%s' to try decrypt\n", fn.c_str()); + return -1; + } + read_len = fread(buffer, sizeof(uint8_t), 4096, f); + if (read_len <= 0) { + LOGERR("Read size during try decrypt failed\n"); + fclose(f); + return -1; + } + if (oaes_decrypt(ctx, buffer, read_len, NULL, &out_len) != OAES_RET_SUCCESS) { + LOGERR("Error: Failed to retrieve required buffer size for trying decryption.\n"); + fclose(f); + return -1; + } + buffer_out = (uint8_t *) calloc(out_len, sizeof(char)); + if (buffer_out == NULL) { + LOGERR("Failed to allocate output buffer for try decrypt.\n"); + fclose(f); + return -1; + } + if (oaes_decrypt(ctx, buffer, read_len, buffer_out, &out_len) != OAES_RET_SUCCESS) { + LOGERR("Failed to decrypt file '%s'\n", fn.c_str()); + fclose(f); + free(buffer_out); + return 0; + } + fclose(f); + if (out_len < 2) { + LOGINFO("Successfully decrypted '%s' but read length %i too small.\n", fn.c_str(), out_len); + free(buffer_out); + return 1; // Decrypted successfully + } + ptr = buffer_out; + firstbyte = *ptr & 0xff; + ptr++; + secondbyte = *ptr & 0xff; + if (firstbyte == 0x1f && secondbyte == 0x8b) { + LOGINFO("Successfully decrypted '%s' and file is compressed.\n", fn.c_str()); + free(buffer_out); + return 3; // Compressed + } + if (out_len >= 262) { + ptr = buffer_out + 257; + if (strncmp((char*)ptr, "ustar", 5) == 0) { + LOGINFO("Successfully decrypted '%s' and file is tar format.\n", fn.c_str()); + free(buffer_out); + return 2; // Tar + } + } + free(buffer_out); + LOGINFO("No errors decrypting '%s' but no known file format.\n", fn.c_str()); + return 1; // Decrypted successfully +#else + LOGERR("Encrypted backup support not included.\n"); + return -1; +#endif +} + +unsigned long TWFunc::Get_File_Size(string Path) { + struct stat st; + + if (stat(Path.c_str(), &st) != 0) + return 0; + return st.st_size; +} + +#ifndef BUILD_TWRPTAR_MAIN + // Returns "/path" from a full /path/to/file.name string TWFunc::Get_Root_Path(string Path) { string Local_Path = Path; @@ -206,15 +367,6 @@ int TWFunc::Recursive_Mkdir(string Path) { return true; } -bool TWFunc::Path_Exists(string Path) { - // Check to see if the Path exists - struct stat st; - if (stat(Path.c_str(), &st) != 0) - return false; - else - return true; -} - void TWFunc::GUI_Operation_Text(string Read_Value, string Default_Text) { string Display_Text; @@ -237,14 +389,6 @@ void TWFunc::GUI_Operation_Text(string Read_Value, string Partition_Name, string DataManager::SetValue("tw_partition", Partition_Name); } -unsigned long TWFunc::Get_File_Size(string Path) { - struct stat st; - - if (stat(Path.c_str(), &st) != 0) - return 0; - return st.st_size; -} - void TWFunc::Copy_Log(string Source, string Destination) { PartitionManager.Mount_By_Path(Destination, false); FILE *destination_log = fopen(Destination.c_str(), "a"); @@ -478,30 +622,6 @@ int TWFunc::write_file(string fn, string& line) { return -1; } -vector<string> TWFunc::split_string(const string &in, char del, bool skip_empty) { - vector<string> res; - - if (in.empty() || del == '\0') - return res; - - string field; - istringstream f(in); - if (del == '\n') { - while(getline(f, field)) { - if (field.empty() && skip_empty) - continue; - res.push_back(field); - } - } else { - while(getline(f, field, del)) { - if (field.empty() && skip_empty) - continue; - res.push_back(field); - } - } - return res; -} - timespec TWFunc::timespec_diff(timespec& start, timespec& end) { timespec temp; @@ -559,13 +679,21 @@ bool TWFunc::Fix_su_Perms(void) { if (!PartitionManager.Mount_By_Path("/system", true)) return false; + string propvalue = System_Property_Get("ro.build.version.sdk"); + string su_perms = "6755"; + if (!propvalue.empty()) { + int sdk_version = atoi(propvalue.c_str()); + if (sdk_version >= 18) + su_perms = "0755"; + } + string file = "/system/bin/su"; if (TWFunc::Path_Exists(file)) { if (chown(file.c_str(), 0, 0) != 0) { LOGERR("Failed to chown '%s'\n", file.c_str()); return false; } - if (tw_chmod(file, "6755") != 0) { + if (tw_chmod(file, su_perms) != 0) { LOGERR("Failed to chmod '%s'\n", file.c_str()); return false; } @@ -576,7 +704,7 @@ bool TWFunc::Fix_su_Perms(void) { LOGERR("Failed to chown '%s'\n", file.c_str()); return false; } - if (tw_chmod(file, "6755") != 0) { + if (tw_chmod(file, su_perms) != 0) { LOGERR("Failed to chmod '%s'\n", file.c_str()); return false; } @@ -587,7 +715,7 @@ bool TWFunc::Fix_su_Perms(void) { LOGERR("Failed to chown '%s'\n", file.c_str()); return false; } - if (tw_chmod(file, "6755") != 0) { + if (tw_chmod(file, "0755") != 0) { LOGERR("Failed to chmod '%s'\n", file.c_str()); return false; } @@ -598,7 +726,7 @@ bool TWFunc::Fix_su_Perms(void) { LOGERR("Failed to chown '%s'\n", file.c_str()); return false; } - if (tw_chmod(file, "6755") != 0) { + if (tw_chmod(file, su_perms) != 0) { LOGERR("Failed to chmod '%s'\n", file.c_str()); return false; } @@ -802,121 +930,6 @@ bool TWFunc::Install_SuperSU(void) { return true; } -int TWFunc::Get_File_Type(string fn) { - string::size_type i = 0; - int firstbyte = 0, secondbyte = 0; - char header[3]; - - ifstream f; - f.open(fn.c_str(), ios::in | ios::binary); - f.get(header, 3); - f.close(); - firstbyte = header[i] & 0xff; - secondbyte = header[++i] & 0xff; - - if (firstbyte == 0x1f && secondbyte == 0x8b) - return 1; // Compressed - else if (firstbyte == 0x4f && secondbyte == 0x41) - return 2; // Encrypted - else - return 0; // Unknown - - return 0; -} - -int TWFunc::Try_Decrypting_File(string fn, string password) { -#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS - OAES_CTX * ctx = NULL; - uint8_t _key_data[32] = ""; - FILE *f; - uint8_t buffer[4096]; - uint8_t *buffer_out = NULL; - uint8_t *ptr = NULL; - size_t read_len = 0, out_len = 0; - int firstbyte = 0, secondbyte = 0, key_len; - size_t _j = 0; - size_t _key_data_len = 0; - - // mostly kanged from OpenAES oaes.c - for( _j = 0; _j < 32; _j++ ) - _key_data[_j] = _j + 1; - _key_data_len = password.size(); - if( 16 >= _key_data_len ) - _key_data_len = 16; - else if( 24 >= _key_data_len ) - _key_data_len = 24; - else - _key_data_len = 32; - memcpy(_key_data, password.c_str(), password.size()); - - ctx = oaes_alloc(); - if (ctx == NULL) { - LOGERR("Failed to allocate OAES\n"); - return -1; - } - - oaes_key_import_data(ctx, _key_data, _key_data_len); - - f = fopen(fn.c_str(), "rb"); - if (f == NULL) { - LOGERR("Failed to open '%s' to try decrypt\n", fn.c_str()); - return -1; - } - read_len = fread(buffer, sizeof(uint8_t), 4096, f); - if (read_len <= 0) { - LOGERR("Read size during try decrypt failed\n"); - fclose(f); - return -1; - } - if (oaes_decrypt(ctx, buffer, read_len, NULL, &out_len) != OAES_RET_SUCCESS) { - LOGERR("Error: Failed to retrieve required buffer size for trying decryption.\n"); - fclose(f); - return -1; - } - buffer_out = (uint8_t *) calloc(out_len, sizeof(char)); - if (buffer_out == NULL) { - LOGERR("Failed to allocate output buffer for try decrypt.\n"); - fclose(f); - return -1; - } - if (oaes_decrypt(ctx, buffer, read_len, buffer_out, &out_len) != OAES_RET_SUCCESS) { - LOGERR("Failed to decrypt file '%s'\n", fn.c_str()); - fclose(f); - free(buffer_out); - return 0; - } - fclose(f); - if (out_len < 2) { - LOGINFO("Successfully decrypted '%s' but read length %i too small.\n", fn.c_str(), out_len); - free(buffer_out); - return 1; // Decrypted successfully - } - ptr = buffer_out; - firstbyte = *ptr & 0xff; - ptr++; - secondbyte = *ptr & 0xff; - if (firstbyte == 0x1f && secondbyte == 0x8b) { - LOGINFO("Successfully decrypted '%s' and file is compressed.\n", fn.c_str()); - free(buffer_out); - return 3; // Compressed - } - if (out_len >= 262) { - ptr = buffer_out + 257; - if (strncmp((char*)ptr, "ustar", 5) == 0) { - LOGINFO("Successfully decrypted '%s' and file is tar format.\n", fn.c_str()); - free(buffer_out); - return 2; // Tar - } - } - free(buffer_out); - LOGINFO("No errors decrypting '%s' but no known file format.\n", fn.c_str()); - return 1; // Decrypted successfully -#else - LOGERR("Encrypted backup support not included.\n"); - return -1; -#endif -} - bool TWFunc::Try_Decrypting_Backup(string Restore_Path, string Password) { DIR* d; @@ -945,31 +958,6 @@ bool TWFunc::Try_Decrypting_Backup(string Restore_Path, string Password) { return true; } -int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) { - pid_t rc_pid; - - rc_pid = waitpid(pid, status, 0); - if (rc_pid > 0) { - if (WEXITSTATUS(*status) == 0) - LOGINFO("%s process ended with RC=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Success - else if (WIFSIGNALED(*status)) { - LOGINFO("%s process ended with signal: %d\n", Child_Name.c_str(), WTERMSIG(*status)); // Seg fault or some other non-graceful termination - return -1; - } else if (WEXITSTATUS(*status) != 0) { - LOGINFO("%s process ended with ERROR=%d\n", Child_Name.c_str(), WEXITSTATUS(*status)); // Graceful exit, but there was an error - return -1; - } - } else { // no PID returned - if (errno == ECHILD) - LOGINFO("%s no child process exist\n", Child_Name.c_str()); - else { - LOGINFO("%s Unexpected error\n", Child_Name.c_str()); - return -1; - } - } - return 0; -} - string TWFunc::Get_Current_Date() { string Current_Date; time_t seconds = time(0); @@ -980,50 +968,56 @@ string TWFunc::Get_Current_Date() { return Current_Date; } -void TWFunc::Auto_Generate_Backup_Name() { +string TWFunc::System_Property_Get(string Prop_Name) { bool mount_state = PartitionManager.Is_Mounted_By_Path("/system"); std::vector<string> buildprop; - if (!PartitionManager.Mount_By_Path("/system", true)) { - DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date()); - return; - } + string propvalue; + if (!PartitionManager.Mount_By_Path("/system", true)) + return propvalue; if (TWFunc::read_file("/system/build.prop", buildprop) != 0) { - LOGINFO("Unable to open /system/build.prop for getting backup name.\n"); + LOGINFO("Unable to open /system/build.prop for getting '%s'.\n", Prop_Name.c_str()); DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date()); if (!mount_state) PartitionManager.UnMount_By_Path("/system", false); - return; + return propvalue; } int line_count = buildprop.size(); int index; size_t start_pos = 0, end_pos; - string propname, propvalue; + string propname; for (index = 0; index < line_count; index++) { end_pos = buildprop.at(index).find("=", start_pos); propname = buildprop.at(index).substr(start_pos, end_pos); - if (propname == "ro.build.display.id") { + if (propname == Prop_Name) { propvalue = buildprop.at(index).substr(end_pos + 1, buildprop.at(index).size()); - string Backup_Name = Get_Current_Date(); - Backup_Name += " " + propvalue; - if (Backup_Name.size() > MAX_BACKUP_NAME_LEN) - Backup_Name.resize(MAX_BACKUP_NAME_LEN); - // Trailing spaces cause problems on some file systems, so remove them - string space_check, space = " "; - space_check = Backup_Name.substr(Backup_Name.size() - 1, 1); - while (space_check == space) { - Backup_Name.resize(Backup_Name.size() - 1); - space_check = Backup_Name.substr(Backup_Name.size() - 1, 1); - } - DataManager::SetValue(TW_BACKUP_NAME, Backup_Name); - break; + if (!mount_state) + PartitionManager.UnMount_By_Path("/system", false); + return propvalue; } } + if (!mount_state) + PartitionManager.UnMount_By_Path("/system", false); + return propvalue; +} + +void TWFunc::Auto_Generate_Backup_Name() { + string propvalue = System_Property_Get("ro.build.display.id"); if (propvalue.empty()) { - LOGINFO("ro.build.display.id not found in build.prop\n"); DataManager::SetValue(TW_BACKUP_NAME, Get_Current_Date()); + return; } - if (!mount_state) - PartitionManager.UnMount_By_Path("/system", false); + string Backup_Name = Get_Current_Date(); + Backup_Name += " " + propvalue; + if (Backup_Name.size() > MAX_BACKUP_NAME_LEN) + Backup_Name.resize(MAX_BACKUP_NAME_LEN); + // Trailing spaces cause problems on some file systems, so remove them + string space_check, space = " "; + space_check = Backup_Name.substr(Backup_Name.size() - 1, 1); + while (space_check == space) { + Backup_Name.resize(Backup_Name.size() - 1); + space_check = Backup_Name.substr(Backup_Name.size() - 1, 1); + } + DataManager::SetValue(TW_BACKUP_NAME, Backup_Name); } void TWFunc::Fixup_Time_On_Boot() @@ -1118,3 +1112,5 @@ void TWFunc::Fixup_Time_On_Boot() settimeofday(&tv, NULL); #endif } + +#endif // ndef BUILD_TWRPTAR_MAIN diff --git a/twrp-functions.hpp b/twrp-functions.hpp index 587d7725e..661ca02db 100644 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -42,20 +42,25 @@ public: static string Get_Path(string Path); // Trims everything after the last / in the string static string Get_Filename(string Path); // Trims the path off of a filename + static int Exec_Cmd(const string& cmd, string &result); //execute a command and return the result as a string by reference + static int Exec_Cmd(const string& cmd); //execute a command + static int Wait_For_Child(pid_t pid, int *status, string Child_Name); // Waits for pid to exit and checks exit status + static bool Path_Exists(string Path); // Returns true if the path exists + static int Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted + static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format + static unsigned long Get_File_Size(string Path); // Returns the size of a file + +#ifndef BUILD_TWRPTAR_MAIN static void install_htc_dumlock(void); // Installs HTC Dumlock static void htc_dumlock_restore_original_boot(void); // Restores the backup of boot from HTC Dumlock static void htc_dumlock_reflash_recovery_to_boot(void); // Reflashes the current recovery to boot static int Recursive_Mkdir(string Path); // Recursively makes the entire path - static bool Path_Exists(string Path); // Returns true if the path exists static void GUI_Operation_Text(string Read_Value, string Default_Text); // Updates text for display in the GUI, e.g. Backing up %partition name% static void GUI_Operation_Text(string Read_Value, string Partition_Name, string Default_Text); // Same as above but includes partition name - static unsigned long Get_File_Size(string Path); // Returns the size of a file static void Update_Log_File(void); // Writes the log to last_log static void Update_Intent_File(string Intent); // Updates intent file static int tw_reboot(RebootCommand command); // Prepares the device for rebooting static void check_and_run_script(const char* script_file, const char* display_name); // checks for the existence of a script, chmods it to 755, then runs it - static int Exec_Cmd(const string& cmd, string &result); //execute a command and return the result as a string by reference - static int Exec_Cmd(const string& cmd); //execute a command static int removeDir(const string path, bool removeParent); //recursively remove a directory static int copy_file(string src, string dst, int mode); //copy file from src to dst with mode permissions static unsigned int Get_D_Type_From_Stat(string Path); // Returns a dirent dt_type value using stat instead of dirent @@ -69,11 +74,8 @@ public: static bool Fix_su_Perms(void); // sets proper permissions for su binaries and superuser apk static int tw_chmod(const string& fn, const string& mode); // chmod function that converts a 3 or 4 char string into st_mode automatically static bool Install_SuperSU(void); // Installs su binary and apk and sets proper permissions - static vector<string> split_string(const string &in, char del, bool skip_empty); - static int Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted - static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format static bool Try_Decrypting_Backup(string Restore_Path, string Password); // true for success, false for failed to decrypt - static int Wait_For_Child(pid_t pid, int *status, string Child_Name); // Waits for pid to exit and checks exit status + static string System_Property_Get(string Prop_Name); // Returns value of Prop_Name from reading /system/build.prop static string Get_Current_Date(void); // Returns the current date in ccyy-m-dd--hh-nn-ss format static void Auto_Generate_Backup_Name(); // Populates TW_BACKUP_NAME with a backup name based on current date and ro.build.display.id from /system/build.prop static void Fixup_Time_On_Boot(); // Fixes time on devices which need it @@ -84,5 +86,8 @@ private: }; extern int Log_Offset; +#else +}; +#endif // ndef BUILD_TWRPTAR_MAIN #endif // _TWRPFUNCTIONS_HPP diff --git a/twrpTar.cpp b/twrpTar.cpp index 824356aae..cc09b78ab 100644 --- a/twrpTar.cpp +++ b/twrpTar.cpp @@ -21,7 +21,6 @@ extern "C" { #include "libtar/libtar.h" #include "twrpTar.h" #include "tarWrite.h" - #include "libcrecovery/common.h" } #include <sys/types.h> #include <sys/stat.h> @@ -39,7 +38,6 @@ extern "C" { #include <sys/mman.h> #include "twrpTar.hpp" #include "twcommon.h" -#include "data.hpp" #include "variables.h" #include "twrp-functions.hpp" @@ -77,6 +75,10 @@ void twrpTar::setsize(unsigned long long backup_size) { Total_Backup_Size = backup_size; } +void twrpTar::setpassword(string pass) { + password = pass; +} + int twrpTar::createTarFork() { int status = 0; pid_t pid, rc_pid; @@ -529,9 +531,7 @@ int twrpTar::extract() { int ret = extractTar(); return ret; } else if (Archive_Current_Type == 2) { - string Password; - DataManager::GetValue("tw_restore_password", Password); - int ret = TWFunc::Try_Decrypting_File(tarfn, Password); + int ret = TWFunc::Try_Decrypting_File(tarfn, password); if (ret < 1) { LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str()); return -1; @@ -675,13 +675,11 @@ int twrpTar::createTar() { char* charTarFile = (char*) tarfn.c_str(); char* charRootDir = (char*) tardir.c_str(); static tartype_t type = { open, close, read, write_tar }; - string Password; if (use_encryption && use_compression) { // Compressed and encrypted Archive_Current_Type = 3; LOGINFO("Using encryption and compression...\n"); - DataManager::GetValue("tw_backup_password", Password); int i, pipes[4]; if (pipe(pipes) < 0) { @@ -738,7 +736,7 @@ int twrpTar::createTar() { dup2(pipes[2], 0); close(1); dup2(output_fd, 1); - if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) { + if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) { LOGERR("execlp openaes ERROR!\n"); close(pipes[2]); close(output_fd); @@ -806,7 +804,6 @@ int twrpTar::createTar() { // Encrypted Archive_Current_Type = 2; LOGINFO("Using encryption...\n"); - DataManager::GetValue("tw_backup_password", Password); int oaesfd[2]; pipe(oaesfd); oaes_pid = fork(); @@ -826,7 +823,7 @@ int twrpTar::createTar() { } dup2(oaesfd[0], 0); // remap stdin dup2(output_fd, 1); // remap stdout to output file - if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) { + if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) { LOGERR("execlp openaes ERROR!\n"); close(output_fd); close(oaesfd[0]); @@ -861,7 +858,6 @@ int twrpTar::openTar() { if (Archive_Current_Type == 3) { LOGINFO("Opening encrypted and compressed backup...\n"); - DataManager::GetValue("tw_restore_password", Password); int i, pipes[4]; if (pipe(pipes) < 0) { @@ -894,7 +890,7 @@ int twrpTar::openTar() { dup2(input_fd, 0); close(1); dup2(pipes[1], 1); - if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) { + if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) { LOGERR("execlp openaes ERROR!\n"); close(input_fd); close(pipes[1]); @@ -938,7 +934,6 @@ int twrpTar::openTar() { } } else if (Archive_Current_Type == 2) { LOGINFO("Opening encrypted backup...\n"); - DataManager::GetValue("tw_restore_password", Password); int oaesfd[2]; pipe(oaesfd); @@ -960,7 +955,7 @@ int twrpTar::openTar() { close(0); // close stdin dup2(oaesfd[1], 1); // remap stdout dup2(input_fd, 0); // remap input fd to stdin - if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) { + if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) { LOGERR("execlp openaes ERROR!\n"); close(input_fd); close(oaesfd[1]); @@ -1119,38 +1114,6 @@ int twrpTar::entryExists(string entry) { return ret; } -unsigned long long twrpTar::uncompressedSize() { - int type = 0; - unsigned long long total_size = 0; - string Tar, Command, result; - vector<string> split; - - Tar = TWFunc::Get_Filename(tarfn); - type = TWFunc::Get_File_Type(tarfn); - if (type == 0) - total_size = TWFunc::Get_File_Size(tarfn); - else { - Command = "pigz -l " + tarfn; - /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '"; - we get the uncompressed size at once. */ - TWFunc::Exec_Cmd(Command, result); - if (!result.empty()) { - /* Expected output: - compressed original reduced name - 95855838 179403776 -1.3% data.yaffs2.win - ^ - split[5] - */ - split = TWFunc::split_string(result, ' ', true); - if (split.size() > 4) - total_size = atoi(split[5].c_str()); - } - } - LOGINFO("%s's uncompressed size: %llu bytes\n", Tar.c_str(), total_size); - - return total_size; -} - extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) { return (ssize_t) write_libtar_buffer(fd, buffer, size); } diff --git a/twrpTar.hpp b/twrpTar.hpp index 17f69594d..a42dea0e1 100644 --- a/twrpTar.hpp +++ b/twrpTar.hpp @@ -51,7 +51,7 @@ public: void setfn(string fn); void setdir(string dir); void setsize(unsigned long long backup_size); - unsigned long long uncompressedSize(); + void setpassword(string pass); public: int use_encryption; @@ -89,6 +89,7 @@ private: string tardir; string tarfn; string basefn; + string password; vector <string> tarexclude; diff --git a/twrpTarMain/Android.mk b/twrpTarMain/Android.mk new file mode 100644 index 000000000..5cd6fe109 --- /dev/null +++ b/twrpTarMain/Android.mk @@ -0,0 +1,71 @@ +LOCAL_PATH:= $(call my-dir) + +# Build static binary +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + twrpTarMain.cpp \ + ../twrp-functions.cpp \ + ../twrpTar.cpp \ + ../tarWrite.c \ + ../twrpDU.cpp +LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN + +LOCAL_C_INCLUDES += bionic external/stlport/stlport +LOCAL_STATIC_LIBRARIES := libc libtar_static libstlport_static libstdc++ + +ifeq ($(TWHAVE_SELINUX), true) + LOCAL_C_INCLUDES += external/libselinux/include + LOCAL_STATIC_LIBRARIES += libselinux + LOCAL_CFLAGS += -DHAVE_SELINUX -g +endif +ifneq ($(RECOVERY_SDCARD_ON_DATA),) + LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA +endif +ifeq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true) + LOCAL_CFLAGS += -DTW_EXCLUDE_ENCRYPTED_BACKUPS +else + LOCAL_STATIC_LIBRARIES += libopenaes_static +endif + +LOCAL_MODULE:= twrpTar_static +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_MODULE_TAGS:= eng +LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +include $(BUILD_EXECUTABLE) + + +# Build shared binary +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + twrpTarMain.cpp \ + ../twrp-functions.cpp \ + ../twrpTar.cpp \ + ../tarWrite.c \ + ../twrpDU.cpp +LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN + +LOCAL_C_INCLUDES += bionic external/stlport/stlport +LOCAL_SHARED_LIBRARIES := libc libtar libstlport libstdc++ + +ifeq ($(TWHAVE_SELINUX), true) + LOCAL_C_INCLUDES += external/libselinux/include + LOCAL_SHARED_LIBRARIES += libselinux + LOCAL_CFLAGS += -DHAVE_SELINUX -g +endif +ifneq ($(RECOVERY_SDCARD_ON_DATA),) + LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA +endif +ifeq ($(TW_EXCLUDE_ENCRYPTED_BACKUPS), true) + LOCAL_CFLAGS += -DTW_EXCLUDE_ENCRYPTED_BACKUPS +else + LOCAL_SHARED_LIBRARIES += libopenaes +endif + +LOCAL_MODULE:= twrpTar +LOCAL_MODULE_TAGS:= eng +LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +include $(BUILD_EXECUTABLE) diff --git a/twrpTarMain/twrpTarMain.cpp b/twrpTarMain/twrpTarMain.cpp new file mode 100644 index 000000000..ef6a5efea --- /dev/null +++ b/twrpTarMain/twrpTarMain.cpp @@ -0,0 +1,164 @@ + +/* + Copyright 2014 TeamWin + This file is part of TWRP/TeamWin Recovery Project. + + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "../twrp-functions.hpp" +#include "../twrpTar.hpp" +#include "../twrpDU.hpp" +#include <string.h> + +twrpDU du; + +void usage() { + printf("twrpTar <action> [options]\n\n"); + printf("actions: -c create\n"); + printf(" -x extract\n\n"); + printf(" -d target directory\n"); + printf(" -t output file\n"); + printf(" -m skip media subfolder (has data media)\n"); + printf(" -z compress backup (/sbin/pigz must be present)\n"); +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + printf(" -e encrypt/decrypt backup followed by password (/sbin/openaes must be present)\n"); + printf(" -u encrypt using userdata encryption (must be used with -e\n"); +#endif + printf("\n\n"); + printf("Example: twrpTar -c -d /cache -t /sdcard/test.tar\n"); + printf(" twrpTar -x -d /cache -t /sdcard/test.tar\n"); +} + +int main(int argc, char **argv) { + twrpTar tar; + int use_encryption = 0, userdata_encryption = 0, has_data_media = 0, use_compression = 0, include_root = 0; + int i, action = 0; + unsigned j; + string Directory, Tar_Filename; +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + string Password; +#endif + + if (argc < 2) { + usage(); + return 0; + } + + if (strcmp(argv[1], "-c") == 0) + action = 1; // create tar + else if (strcmp(argv[1], "-x") == 0) + action = 2; // extract tar + else { + printf("Invalid action '%s' specified.\n", argv[1]); + usage(); + return -1; + } + + for (i = 2; i < argc; i++) { + if (strcmp(argv[i], "-d") == 0) { + i++; + if (argc <= i) { + printf("No argument specified for %s\n", argv[i - 1]); + usage(); + return -1; + } else { + Directory = argv[i]; + } + } else if (strcmp(argv[i], "-t") == 0) { + i++; + if (argc <= i) { + printf("No argument specified for %s\n", argv[i - 1]); + usage(); + return -1; + } else { + Tar_Filename = argv[i]; + } + } else if (strcmp(argv[i], "-e") == 0) { +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + i++; + if (argc <= i) { + printf("No argument specified for %s\n", argv[i - 1]); + usage(); + return -1; + } else { + use_encryption = 1; + Password = argv[i]; + } +#else + printf("Encrypted tar file support not present\n"); + usage(); + return -1; +#endif + } else if (strcmp(argv[i], "-m") == 0) { + if (action == 2) + printf("NOTE: %s option not needed when extracting.\n", argv[i]); + has_data_media = 1; + } else if (strcmp(argv[i], "-z") == 0) { + if (action == 2) + printf("NOTE: %s option not needed when extracting.\n", argv[i]); + use_compression = 1; + } else if (strcmp(argv[i], "-u") == 0) { +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + if (action == 2) + printf("NOTE: %s option not needed when extracting.\n", argv[i]); + userdata_encryption = 1; +#else + printf("Encrypted tar file support not present\n"); + usage(); + return -1; +#endif + } + } + + vector<string> excludedirs = du.get_absolute_dirs(); + for (j = 0; j < excludedirs.size(); ++j) { + tar.setexcl(excludedirs.at(j)); + } + tar.has_data_media = has_data_media; + tar.setdir(Directory); + tar.setfn(Tar_Filename); + tar.setsize(du.Get_Folder_Size(Directory)); + tar.use_compression = use_compression; +#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS + if (userdata_encryption && !use_encryption) { + printf("userdata encryption set without encryption option\n"); + usage(); + return -1; + } + if (use_encryption) { + tar.use_encryption = use_encryption; + tar.userdata_encryption = userdata_encryption; + tar.setpassword(Password); + } else { + use_encryption = false; + } +#endif + if (action == 1) { + if (tar.createTarFork() != 0) { + sync(); + return -1; + } + sync(); + printf("\n\ntar created successfully.\n"); + } else if (action == 2) { + if (tar.extractTarFork() != 0) { + sync(); + return -1; + } + sync(); + printf("\n\ntar extracted successfully.\n"); + } + return 0; +} |