From 5112731666070037ac8ed78dfdad57a11bd4cb6d Mon Sep 17 00:00:00 2001 From: Dees_Troy Date: Sat, 8 Sep 2012 13:08:49 -0400 Subject: Improve storage size code, mount, unmount Add flag parsing from recovery.fstab --- data.cpp | 6 -- etc/init.rc | 1 - gui/action.cpp | 22 ++--- partition.cpp | 259 +++++++++++++++++++++++++++++++++++++++------------ partitionmanager.cpp | 242 +++++++++++++++++++++++++++++++++++++---------- partitions.hpp | 12 ++- recovery.cpp | 5 +- roots.cpp | 3 +- 8 files changed, 410 insertions(+), 140 deletions(-) diff --git a/data.cpp b/data.cpp index 92e2e413f..296843546 100644 --- a/data.cpp +++ b/data.cpp @@ -296,14 +296,8 @@ int DataManager::SetValue(const string varName, int value, int persist /* = 0 */ if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) { if (value == 0) { str = GetStrValue(TW_INTERNAL_PATH); - if (GetIntValue(TW_HAS_DATA_MEDIA) == 1) { - LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((dat.sze - dat.used) / 1048576LLU)); - } else { - LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcint.sze - sdcint.used) / 1048576LLU)); - } } else { str = GetStrValue(TW_EXTERNAL_PATH); - LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcext.sze - sdcext.used) / 1048576LLU)); } } else if (GetIntValue(TW_HAS_INTERNAL) == 1) str = GetStrValue(TW_INTERNAL_PATH); diff --git a/etc/init.rc b/etc/init.rc index a6f2f909e..e26027a13 100644 --- a/etc/init.rc +++ b/etc/init.rc @@ -10,7 +10,6 @@ on init symlink /system/etc /etc - mkdir /emmc mkdir /system mkdir /data mkdir /cache diff --git a/gui/action.cpp b/gui/action.cpp index db4c9c415..aee56849f 100644 --- a/gui/action.cpp +++ b/gui/action.cpp @@ -416,14 +416,11 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */) { string cmd; if (arg == "EXTERNAL") - cmd = "mount " + DataManager::GetStrValue(TW_EXTERNAL_MOUNT); + PartitionManager.Mount_By_Path(DataManager::GetStrValue(TW_EXTERNAL_MOUNT), true); else if (arg == "INTERNAL") - cmd = "mount " + DataManager::GetStrValue(TW_INTERNAL_MOUNT); + PartitionManager.Mount_By_Path(DataManager::GetStrValue(TW_INTERNAL_MOUNT), true); else - cmd = "mount " + arg; - __system(cmd.c_str()); - if (arg == "/data" && DataManager::GetIntValue(TW_HAS_DATADATA) == 1) - __system("mount /datadata"); + PartitionManager.Mount_By_Path(arg, true); } else ui_print("Simulating actions...\n"); return 0; @@ -443,16 +440,11 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */) { string cmd; if (arg == "EXTERNAL") - cmd = "umount " + DataManager::GetStrValue(TW_EXTERNAL_MOUNT); + PartitionManager.UnMount_By_Path(DataManager::GetStrValue(TW_EXTERNAL_MOUNT), true); else if (arg == "INTERNAL") - cmd = "umount " + DataManager::GetStrValue(TW_INTERNAL_MOUNT); - else if (DataManager::GetIntValue(TW_DONT_UNMOUNT_SYSTEM) == 1 && (arg == "system" || arg == "/system")) - return 0; + PartitionManager.UnMount_By_Path(DataManager::GetStrValue(TW_INTERNAL_MOUNT), true); else - cmd = "umount " + arg; - __system(cmd.c_str()); - if (arg == "/data" && DataManager::GetIntValue(TW_HAS_DATADATA) == 1) - __system("umount /datadata"); + PartitionManager.UnMount_By_Path(arg, true); } else ui_print("Simulating actions...\n"); return 0; @@ -549,7 +541,7 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */) } else if (arg == "external") { DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 1); } - if (PartitionManager.Mount_Settings_Storage(true)) { + if (PartitionManager.Mount_Current_Storage(true)) { if (arg == "internal") { // Save the current zip location to the external variable DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, DataManager::GetStrValue(TW_ZIP_LOCATION_VAR)); diff --git a/partition.cpp b/partition.cpp index 29a20dc9f..017af8829 100644 --- a/partition.cpp +++ b/partition.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "variables.h" #include "common.h" @@ -35,8 +36,6 @@ extern "C" { #include "extra-functions.h" int __system(const char *command); - FILE * __popen(const char *program, const char *type); - int __pclose(FILE *iop); } TWPartition::TWPartition(void) { @@ -81,13 +80,13 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH]; int line_len = Line.size(), index = 0, item_index = 0; char* ptr; + string Flags; strncpy(full_line, Line.c_str(), line_len); - while (index < line_len) { + for (index = 0; index < line_len; index++) { if (full_line[index] <= 32) full_line[index] = '\0'; - index++; } string mount_pt(full_line); Mount_Point = mount_pt; @@ -124,6 +123,10 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { // Partition length ptr += 7; Length = atoi(ptr); + } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) { + // Custom flags, save for later so that new values aren't overwritten by defaults + ptr += 6; + Flags = ptr; } else { // Unhandled data LOGI("Unhandled fstab information: '%s', %i\n", ptr, index); @@ -144,14 +147,16 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { if (Mount_Point == "/system") { Display_Name = "System"; Wipe_Available_in_GUI = true; - Update_Size(Display_Error); - int backup_display_size = (int)(Backup_Size / 1048576LLU); - DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size); } else if (Mount_Point == "/data") { Display_Name = "Data"; Wipe_Available_in_GUI = true; + Wipe_During_Factory_Reset = true; #ifdef RECOVERY_SDCARD_ON_DATA Has_Data_Media = true; + Is_Storage = true; + Storage_Path = "/data/media"; + Make_Dir("/sdcard", Display_Error); + Make_Dir("/emmc", Display_Error); #endif #ifdef TW_INCLUDE_CRYPTO Can_Be_Encrypted = true; @@ -161,36 +166,23 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { DataManager::SetValue(TW_IS_ENCRYPTED, 1); DataManager::SetValue(TW_CRYPTO_PASSWORD, ""); DataManager::SetValue("tw_crypto_display", ""); - } else - Update_Size(Display_Error); -#else - Update_Size(Display_Error); + } #endif - int backup_display_size = (int)(Backup_Size / 1048576LLU); - DataManager::SetValue(TW_BACKUP_DATA_SIZE, backup_display_size); } else if (Mount_Point == "/cache") { Display_Name = "Cache"; Wipe_Available_in_GUI = true; + Wipe_During_Factory_Reset = true; Update_Size(Display_Error); - int backup_display_size = (int)(Backup_Size / 1048576LLU); - DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size); } else if (Mount_Point == "/datadata") { + Wipe_During_Factory_Reset = true; Display_Name = "DataData"; Is_SubPartition = true; SubPartition_Of = "/data"; - Update_Size(Display_Error); DataManager::SetValue(TW_HAS_DATADATA, 1); } else if (Mount_Point == "/sd-ext") { + Wipe_During_Factory_Reset = true; Display_Name = "SD-Ext"; Wipe_Available_in_GUI = true; - Update_Size(Display_Error); - int backup_display_size = (int)(Backup_Size / 1048576LLU); - DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size); - if (Backup_Size == 0) { - DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0); - DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0); - } else - DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1); } else Update_Size(Display_Error); } else if (Is_Image(Fstab_File_System)) { @@ -214,7 +206,62 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { } } - return 1; + // Process any custom flags + if (Flags.size() > 0) + Process_Flags(Flags, Display_Error); + + return true; +} + +bool TWPartition::Process_Flags(string Flags, bool Display_Error) { + char flags[MAX_FSTAB_LINE_LENGTH]; + int flags_len, index = 0; + char* ptr; + + strcpy(flags, Flags.c_str()); + flags_len = Flags.size(); + for (index = 0; index < flags_len; index++) { + if (flags[index] == ';') + flags[index] = '\0'; + } + + index = 0; + while (index < flags_len) { + while (index < flags_len && flags[index] == '\0') + index++; + if (index >= flags_len) + continue; + ptr = flags + index; + if (strcmp(ptr, "removable") == 0) { + Removable = true; + } else if (strcmp(ptr, "storage") == 0) { + Is_Storage = true; + } else if (strlen(ptr) > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) { + ptr += 13; + Is_SubPartition = true; + SubPartition_Of = ptr; + } else if (strlen(ptr) > 8 && strncmp(ptr, "symlink=", 8) == 0) { + ptr += 8; + Symlink_Path = ptr; + } else if (strlen(ptr) > 8 && strncmp(ptr, "display=", 8) == 0) { + ptr += 8; + Display_Name = ptr; + } else if (strlen(ptr) > 10 && strncmp(ptr, "blocksize=", 10) == 0) { + ptr += 10; + Format_Block_Size = atoi(ptr); + } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) { + ptr += 7; + Length = atoi(ptr); + } else { + if (Display_Error) + LOGE("Unhandled flag: '%s'\n", ptr); + else + LOGI("Unhandled flag: '%s'\n", ptr); + } + while (index < flags_len && flags[index] != '\0') + index++; + } + return true; } bool TWPartition::Is_File_System(string File_System) { @@ -238,6 +285,22 @@ bool TWPartition::Is_Image(string File_System) { return false; } +bool TWPartition::Make_Dir(string Path, bool Display_Error) { + if (!Path_Exists(Path)) { + if (mkdir(Path.c_str(), 0777) == -1) { + if (Display_Error) + LOGE("Can not create '%s' folder.\n", Path.c_str()); + else + LOGI("Can not create '%s' folder.\n", Path.c_str()); + return false; + } else { + LOGI("Created '%s' folder.\n", Path.c_str()); + return true; + } + } + return true; +} + void TWPartition::Setup_File_System(bool Display_Error) { struct statfs st; @@ -252,15 +315,7 @@ void TWPartition::Setup_File_System(bool Display_Error) { Is_Present = true; } // Make the mount point folder if it doesn't exist - if (!Path_Exists(Mount_Point.c_str())) { - if (mkdir(Mount_Point.c_str(), 0777) == -1) { - if (Display_Error) - LOGE("Can not create '%s' folder.\n", Mount_Point.c_str()); - else - LOGI("Can not create '%s' folder.\n", Mount_Point.c_str()); - } else - LOGI("Created '%s' folder.\n", Mount_Point.c_str()); - } + Make_Dir(Mount_Point, Display_Error); Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; Backup_Method = FILES; @@ -315,7 +370,30 @@ void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) { } } -bool TWPartition::Get_Size_Via_df(string Path, bool Display_Error) { +bool TWPartition::Get_Size_Via_statfs(bool Display_Error) { + struct statfs st; + string Local_Path = Mount_Point + "/."; + + if (!Mount(Display_Error)) + return false; + + if (statfs(Local_Path.c_str(), &st) != 0) { + if (!Removable) { + if (Display_Error) + LOGE("Unable to statfs '%s'\n", Local_Path.c_str()); + else + LOGI("Unable to statfs '%s'\n", Local_Path.c_str()); + } + return false; + } + Size = (st.f_blocks * st.f_bsize); + Used = ((st.f_blocks - st.f_bfree) * st.f_bsize); + Free = (st.f_bfree * st.f_bsize); + Backup_Size = Used; + return true; +} + +bool TWPartition::Get_Size_Via_df(bool Display_Error) { FILE* fp; char command[255], line[512]; int include_block = 1; @@ -325,10 +403,13 @@ bool TWPartition::Get_Size_Via_df(string Path, bool Display_Error) { return false; min_len = Block_Device.size() + 2; - sprintf(command, "df %s", Path.c_str()); - fp = __popen(command, "r"); - if (fp == NULL) + sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str()); + __system(command); + fp = fopen("/tmp/dfoutput.txt", "rt"); + if (fp == NULL) { + LOGI("Unable to open /tmp/dfoutput.txt.\n"); return false; + } while (fgets(line, sizeof(line), fp) != NULL) { @@ -362,19 +443,42 @@ bool TWPartition::Get_Size_Via_df(string Path, bool Display_Error) { return true; } -unsigned long long TWPartition::Get_Size_Via_du(string Path, bool Display_Error) { - char cmd[512]; - sprintf(cmd, "du -sk %s | awk '{ print $1 }'", Path.c_str()); +unsigned long long TWPartition::Get_Folder_Size(string Path, bool Display_Error) { + DIR* d; + struct dirent* de; + struct stat st; + char path2[1024], filename[1024]; + unsigned long long dusize = 0; - FILE *fp; - fp = __popen(cmd, "r"); - - char str[512]; - fgets(str, sizeof(str), fp); - __pclose(fp); + // Make a copy of path in case the data in the pointer gets overwritten later + strcpy(path2, Path.c_str()); - unsigned long long dusize = atol(str); - dusize *= 1024ULL; + d = opendir(path2); + if (d == NULL) + { + LOGE("error opening '%s'\n", path2); + return 0; + } + + while ((de = readdir(d)) != NULL) + { + if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) + { + strcpy(filename, path2); + strcat(filename, "/"); + strcat(filename, de->d_name); + dusize += Get_Folder_Size(filename, Display_Error); + } + else if (de->d_type == DT_REG) + { + strcpy(filename, path2); + strcat(filename, "/"); + strcat(filename, de->d_name); + stat(filename, &st); + dusize += (unsigned long long)(st.st_size); + } + } + closedir(d); return dusize; } @@ -456,6 +560,8 @@ bool TWPartition::Mount(bool Display_Error) { } else if (!Can_Be_Mounted) { return false; } + if (Removable) + Check_FS_Type(); if (Is_Decrypted) { if (mount(Decrypted_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) { Check_FS_Type(); @@ -465,10 +571,16 @@ bool TWPartition::Mount(bool Display_Error) { else LOGI("Unable to mount decrypted block device '%s' to '%s'\n", Decrypted_Block_Device.c_str(), Mount_Point.c_str()); return false; - } else + } else { + if (Removable) + Update_Size(Display_Error); return true; - } else + } + } else { + if (Removable) + Update_Size(Display_Error); return true; + } } if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) { Check_FS_Type(); @@ -482,13 +594,21 @@ bool TWPartition::Mount(bool Display_Error) { else LOGI("Unable to mount '%s'\n", Mount_Point.c_str()); return false; - } else + } else { + if (Removable) + Update_Size(Display_Error); return true; + } } else return false; - } else + } else { + if (Removable) + Update_Size(Display_Error); return true; + } } + if (Removable) + Update_Size(Display_Error); return true; } @@ -555,10 +675,12 @@ void TWPartition::Check_FS_Type() { return; // Running blkid on some mtd devices causes a massive crash if (Is_Decrypted) - blkCommand = "blkid " + Decrypted_Block_Device; + blkCommand = "blkid " + Decrypted_Block_Device + " > /tmp/blkidoutput.txt"; else - blkCommand = "blkid " + Block_Device; - fp = __popen(blkCommand.c_str(), "r"); + blkCommand = "blkid " + Block_Device + " > /tmp/blkidoutput.txt"; + + __system(blkCommand.c_str()); + fp = fopen("/tmp/blkidoutput.txt", "rt"); while (fgets(blkOutput, sizeof(blkOutput), fp) != NULL) { blk = blkOutput; @@ -672,20 +794,33 @@ bool TWPartition::Restore_Flash_Image(string restore_folder) { } bool TWPartition::Update_Size(bool Display_Error) { + bool ret = false; + if (!Can_Be_Mounted) return false; - if (!Get_Size_Via_df(Mount_Point, Display_Error)) + if (!Mount(Display_Error)) return false; + + ret = Get_Size_Via_statfs(Display_Error); + if (!ret || Size == 0) + if (!Get_Size_Via_df(Display_Error)) + return false; + if (Has_Data_Media) { if (Mount(Display_Error)) { - unsigned long long data_used, data_media_used, actual_data; - data_used = Get_Size_Via_du("/data/", Display_Error); - data_media_used = Get_Size_Via_du("/data/media/", Display_Error); - actual_data = data_used - data_media_used; + unsigned long long data_media_used, actual_data; + data_media_used = Get_Folder_Size("/data/media", Display_Error); + actual_data = Used - data_media_used; Backup_Size = actual_data; + int bak = (int)(Backup_Size / 1048576LLU); + int total = (int)(Size / 1048576LLU); + int us = (int)(Used / 1048576LLU); + int fre = (int)(Free / 1048576LLU); + int datmed = (int)(data_media_used / 1048576LLU); + LOGI("Data backup size is %iMB, size: %iMB, used: %iMB, free: %iMB, in data/media: %iMB.\n", bak, total, us, fre, datmed); } else return false; } return true; -} \ No newline at end of file +} diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 2e50641db..b30e3b729 100644 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -71,6 +71,7 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) else LOGI("Error creating fstab\n"); } + Update_System_Details(); return true; } @@ -85,12 +86,20 @@ int TWPartitionManager::Write_Fstab(void) { return false; } for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { - if ((*iter)->Can_Be_Mounted && (*iter)->Is_Present) { + if ((*iter)->Can_Be_Mounted) { if ((*iter)->Is_Decrypted) Line = (*iter)->Decrypted_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n"; else Line = (*iter)->Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n"; fputs(Line.c_str(), fp); + // Handle subpartition tracking + if ((*iter)->Is_SubPartition) { + TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of); + if (ParentPartition) + ParentPartition->Has_SubPartition = true; + else + LOGE("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str()); + } } } fclose(fp); @@ -101,99 +110,180 @@ int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) { std::vector::iterator iter; int ret = false; bool found = false; - string Local_Path = Path; - - // Make sure that we have a leading slash - if (Local_Path.substr(0, 1) != "/") - Local_Path = "/" + Local_Path; - - // Trim the path to get the root path only - size_t position = Local_Path.find("/", 2); - if (position != string::npos) { - Local_Path.resize(position); - } + string Local_Path = Get_Root_Path(Path); // Iterate through all partitions for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { if ((*iter)->Mount_Point == Local_Path) { ret = (*iter)->Mount(Display_Error); found = true; - } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) + } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) { (*iter)->Mount(Display_Error); + } } if (found) { return ret; } else if (Display_Error) { - LOGE("Unable to find partition for path '%s'\n", Local_Path.c_str()); + LOGE("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str()); } else { - LOGI("Unable to find partition for path '%s'\n", Local_Path.c_str()); + LOGI("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str()); } return false; } int TWPartitionManager::Mount_By_Block(string Block, bool Display_Error) { - std::vector::iterator iter; + TWPartition* Part = Find_Partition_By_Block(Block); - for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { - if ((*iter)->Block_Device == Block) - return (*iter)->Mount(Display_Error); - else if ((*iter)->Alternate_Block_Device == Block) - return (*iter)->Mount(Display_Error); + if (Part) { + if (Part->Has_SubPartition) { + std::vector::iterator subpart; + + for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) + (*subpart)->Mount(Display_Error); + } + return Part->Mount(Display_Error); + } else + return Part->Mount(Display_Error); } if (Display_Error) - LOGE("Unable to find partition for block '%s'\n", Block.c_str()); + LOGE("Mount: Unable to find partition for block '%s'\n", Block.c_str()); else - LOGI("Unable to find partition for block '%s'\n", Block.c_str()); + LOGI("Mount: Unable to find partition for block '%s'\n", Block.c_str()); return false; } int TWPartitionManager::Mount_By_Name(string Name, bool Display_Error) { - std::vector::iterator iter; + TWPartition* Part = Find_Partition_By_Name(Name); - for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { - if ((*iter)->Display_Name == Name) - return (*iter)->Mount(Display_Error); + if (Part) { + if (Part->Has_SubPartition) { + std::vector::iterator subpart; + + for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) + (*subpart)->Mount(Display_Error); + } + return Part->Mount(Display_Error); + } else + return Part->Mount(Display_Error); } if (Display_Error) - LOGE("Unable to find partition for name '%s'\n", Name.c_str()); + LOGE("Mount: Unable to find partition for name '%s'\n", Name.c_str()); else - LOGI("Unable to find partition for name '%s'\n", Name.c_str()); + LOGI("Mount: Unable to find partition for name '%s'\n", Name.c_str()); return false; - return 1; } int TWPartitionManager::UnMount_By_Path(string Path, bool Display_Error) { - LOGI("STUB TWPartitionManager::UnMount_By_Path, Path: '%s', Display_Error: %i\n", Path.c_str(), Display_Error); - return 1; + std::vector::iterator iter; + int ret = false; + bool found = false; + string Local_Path = Get_Root_Path(Path); + + // Iterate through all partitions + for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { + if ((*iter)->Mount_Point == Local_Path) { + ret = (*iter)->UnMount(Display_Error); + found = true; + } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) { + (*iter)->UnMount(Display_Error); + } + } + if (found) { + return ret; + } else if (Display_Error) { + LOGE("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str()); + } else { + LOGI("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str()); + } + return false; } int TWPartitionManager::UnMount_By_Block(string Block, bool Display_Error) { - LOGI("STUB TWPartitionManager::UnMount_By_Block, Block: '%s', Display_Error: %i\n", Block.c_str(), Display_Error); - return 1; + TWPartition* Part = Find_Partition_By_Block(Block); + + if (Part) { + if (Part->Has_SubPartition) { + std::vector::iterator subpart; + + for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) + (*subpart)->UnMount(Display_Error); + } + return Part->UnMount(Display_Error); + } else + return Part->UnMount(Display_Error); + } + if (Display_Error) + LOGE("UnMount: Unable to find partition for block '%s'\n", Block.c_str()); + else + LOGI("UnMount: Unable to find partition for block '%s'\n", Block.c_str()); + return false; } int TWPartitionManager::UnMount_By_Name(string Name, bool Display_Error) { - LOGI("STUB TWPartitionManager::UnMount_By_Name, Name: '%s', Display_Error: %i\n", Name.c_str(), Display_Error); - return 1; + TWPartition* Part = Find_Partition_By_Name(Name); + + if (Part) { + if (Part->Has_SubPartition) { + std::vector::iterator subpart; + + for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) + (*subpart)->UnMount(Display_Error); + } + return Part->UnMount(Display_Error); + } else + return Part->UnMount(Display_Error); + } + if (Display_Error) + LOGE("UnMount: Unable to find partition for name '%s'\n", Name.c_str()); + else + LOGI("UnMount: Unable to find partition for name '%s'\n", Name.c_str()); + return false; } int TWPartitionManager::Is_Mounted_By_Path(string Path) { - LOGI("STUB TWPartitionManager::Is_Mounted_By_Path, Path: '%s'\n", Path.c_str()); - return 1; + TWPartition* Part = Find_Partition_By_Path(Path); + + if (Part) + return Part->Is_Mounted(); + else + LOGI("Is_Mounted: Unable to find partition for path '%s'\n", Path.c_str()); + return false; } int TWPartitionManager::Is_Mounted_By_Block(string Block) { - LOGI("STUB TWPartitionManager::Is_Mounted_By_Block, Block: '%s'\n", Block.c_str()); - return 1; + TWPartition* Part = Find_Partition_By_Block(Block); + + if (Part) + return Part->Is_Mounted(); + else + LOGI("Is_Mounted: Unable to find partition for block '%s'\n", Block.c_str()); + return false; } int TWPartitionManager::Is_Mounted_By_Name(string Name) { - LOGI("STUB TWPartitionManager::Is_Mounted_By_Name, Name: '%s'\n", Name.c_str()); - return 1; + TWPartition* Part = Find_Partition_By_Name(Name); + + if (Part) + return Part->Is_Mounted(); + else + LOGI("Is_Mounted: Unable to find partition for name '%s'\n", Name.c_str()); + return false; } int TWPartitionManager::Mount_Current_Storage(bool Display_Error) { - return Mount_By_Path(DataManager::GetCurrentStoragePath(), Display_Error); + string current_storage_path = DataManager::GetCurrentStoragePath(); + + if (Mount_By_Path(current_storage_path, Display_Error)) { + TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path); + if (FreeStorage) + DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU)); + return true; + } + return false; } int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) { @@ -202,21 +292,32 @@ int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) { TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) { std::vector::iterator iter; + string Local_Path = Get_Root_Path(Path); for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { - if ((*iter)->Mount_Point == Path) + if ((*iter)->Mount_Point == Local_Path) return (*iter); } return NULL; } TWPartition* TWPartitionManager::Find_Partition_By_Block(string Block) { - LOGI("STUB TWPartitionManager::Find_Partition_By_Block, Block: '%s'\n", Block.c_str()); + std::vector::iterator iter; + + for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { + if ((*iter)->Block_Device == Block || (*iter)->Alternate_Block_Device == Block || ((*iter)->Is_Decrypted && (*iter)->Decrypted_Block_Device == Block)) + return (*iter); + } return NULL; } TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) { - LOGI("STUB TWPartitionManager::Find_Partition_By_Name, Name: '%s'\n", Name.c_str()); + std::vector::iterator iter; + + for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { + if ((*iter)->Display_Name == Name) + return (*iter); + } return NULL; } @@ -256,18 +357,44 @@ int TWPartitionManager::Factory_Reset(void) { } void TWPartitionManager::Refresh_Sizes(void) { - LOGI("STUB TWPartitionManager::Refresh_Sizes\n"); + Update_System_Details(); return; } void TWPartitionManager::Update_System_Details(void) { std::vector::iterator iter; + int data_size = 0; LOGI("Updating system details...\n"); for (iter = Partitions.begin(); iter != Partitions.end(); iter++) { - (*iter)->Check_FS_Type(); - (*iter)->Update_Size(false); + if ((*iter)->Can_Be_Mounted) { + (*iter)->Update_Size(true); + if ((*iter)->Mount_Point == "/system") { + int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU); + DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size); + } else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") { + data_size += (int)((*iter)->Backup_Size / 1048576LLU); + } else if ((*iter)->Mount_Point == "/cache") { + int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU); + DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size); + } else if ((*iter)->Mount_Point == "/sd-ext") { + int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU); + DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size); + if ((*iter)->Backup_Size == 0) { + DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0); + DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0); + } else + DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1); + } + } } + DataManager::SetValue(TW_BACKUP_DATA_SIZE, data_size); + string current_storage_path = DataManager::GetCurrentStoragePath(); + TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path); + if (FreeStorage) + DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU)); + else + LOGI("Unable to find storage partition '%s'.\n", current_storage_path.c_str()); if (!Write_Fstab()) LOGE("Error creating fstab\n"); return; @@ -318,4 +445,19 @@ int TWPartitionManager::Decrypt_Device(string Password) { return -1; #endif return 1; -} \ No newline at end of file +} + +string TWPartitionManager::Get_Root_Path(string Path) { + string Local_Path = Path; + + // Make sure that we have a leading slash + if (Local_Path.substr(0, 1) != "/") + Local_Path = "/" + Local_Path; + + // Trim the path to get the root path only + size_t position = Local_Path.find("/", 2); + if (position != string::npos) { + Local_Path.resize(position); + } + return Local_Path; +} diff --git a/partitions.hpp b/partitions.hpp index 13ce02876..5ed723c95 100644 --- a/partitions.hpp +++ b/partitions.hpp @@ -52,7 +52,7 @@ public: virtual bool Wipe(); // Wipes the partition virtual bool Backup(string backup_folder); // Backs up the partition to the folder specified virtual bool Restore(string restore_folder); // Restores the partition using the backup folder provided - static string Backup_Method_By_Name(); // Returns a string of the backup method for human readable output + virtual string Backup_Method_By_Name(); // Returns a string of the backup method for human readable output virtual bool Decrypt(string Password); // Decrypts the partition, return 0 for failure and -1 for success virtual bool Wipe_Encryption(); // Ignores wipe commands for /data/media devices and formats the original block device virtual void Check_FS_Type(); // Checks the fs type using blkid, does not do anything on MTD / yaffs2 because this crashes on some devices @@ -67,6 +67,7 @@ protected: bool Wipe_During_Factory_Reset; // Indicates that this partition is wiped during a factory reset bool Wipe_Available_in_GUI; // Inidcates that the wipe can be user initiated in the GUI system bool Is_SubPartition; // Indicates that this partition is a sub-partition of another partition (e.g. datadata is a sub-partition of data) + bool Has_SubPartition; // Indicates that this partition has a sub-partition string SubPartition_Of; // Indicates which partition is the parent partition of this partition (e.g. /data is the parent partition of /datadata) string Symlink_Path; // Symlink path (e.g. /data/media) string Symlink_Mount_Point; // /sdcard could be the symlink mount point for /data/media @@ -95,6 +96,7 @@ protected: int Format_Block_Size; // Block size for formatting private: + bool Process_Flags(string Flags, bool Display_Error); // Process custom fstab flags bool Is_File_System(string File_System); // Checks to see if the file system given is considered a file system bool Is_Image(string File_System); // Checks to see if the file system given is considered an image void Setup_File_System(bool Display_Error); // Sets defaults for a file system partition @@ -102,7 +104,6 @@ private: bool Path_Exists(string Path); // Checks to see if the Path exists in the file system void Find_Real_Block_Device(string& Block_Device, bool Display_Error); // Checks the block device given and follows symlinks until it gets to the real block device bool Find_Partition_Size(); // Finds the partition size from /proc/partitions - bool Get_Size_Via_df(string Path, bool Display_Error); // Uses df to get sizes unsigned long long Get_Size_Via_du(string Path, bool Display_Error); // Uses du to get sizes void Flip_Block_Device(); // Flips the Block_Device and Alternate_Block_Device bool Wipe_EXT23(); // Formats as ext3 or ext2 @@ -117,6 +118,10 @@ private: bool Restore_Tar(string restore_folder); // Restore using tar for file systems bool Restore_DD(string restore_folder); // Restore using dd for emmc memory types bool Restore_Flash_Image(string restore_folder); // Restore using flash_image for MTD memory types + bool Get_Size_Via_statfs(bool Display_Error); // Get Partition size, used, and free space using statfs + bool Get_Size_Via_df(bool Display_Error); // Get Partition size, used, and free space using df command + unsigned long long Get_Folder_Size(string Path, bool Display_Error); // Gets the size of the files in a folder and all of its subfolders + bool Make_Dir(string Path, bool Display_Error); // Creates a directory if it doesn't already exist friend class TWPartitionManager; }; @@ -154,9 +159,10 @@ public: virtual void Refresh_Sizes(); // Refreshes size data of partitions virtual void Update_System_Details(); // Updates fstab, file systems, sizes, etc. virtual int Decrypt_Device(string Password); // Attempt to decrypt any encrypted partitions + virtual string Get_Root_Path(string Path); // Trims any trailing folders or filenames from the path, also adds a leading / if not present private: - std::vector Partitions; + std::vector Partitions; // Vector list of all partitions }; extern TWPartitionManager PartitionManager; diff --git a/recovery.cpp b/recovery.cpp index 319cdc72a..450f36330 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -51,6 +51,7 @@ extern "C" { #include "gui/gui.h" } #include "partitions.hpp" +#include "variables.h" TWPartitionManager PartitionManager; char device_id[64]; @@ -787,7 +788,7 @@ main(int argc, char **argv) { return 0; } - printf("Starting TWRP %s on %s", EXPAND(TW_VERSION_STR), ctime(&start)); + printf("Starting TWRP %s on %s", TW_VERSION_STR, ctime(&start)); // Recovery needs to install world-readable files, so clear umask // set by init umask(0); @@ -802,7 +803,7 @@ main(int argc, char **argv) { // Load default values to set DataManager constants and handle ifdefs DataManager_LoadDefaults(); printf("Starting the UI..."); - printf(" result was: %i\n", gui_init()); + gui_init(); printf("=> Installing busybox into /sbin\n"); __system("/sbin/bbinstall.sh"); // Let's install busybox printf("=> Linking mtab\n"); diff --git a/roots.cpp b/roots.cpp index 3bd680157..e74747378 100644 --- a/roots.cpp +++ b/roots.cpp @@ -40,7 +40,8 @@ static int parse_options(char* options, Volume* volume) { while ((option = strtok(options, ","))) { options = NULL; - if (strncmp(option, "length=", 7) == 0) { + if (strncmp(option, "flags=", 6) == 0) continue; + if (strncmp(option, "length=", 7) == 0) { volume->length = strtoll(option+7, NULL, 10); } else { LOGE("bad option \"%s\"\n", option); -- cgit v1.2.3