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 --- partition.cpp | 259 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 197 insertions(+), 62 deletions(-) (limited to 'partition.cpp') 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 +} -- cgit v1.2.3