From 7c2dec8020f592fac48fea370e06f6bfd00e2798 Mon Sep 17 00:00:00 2001 From: Dees_Troy Date: Wed, 26 Sep 2012 09:49:14 -0400 Subject: Add backup size checking Converted bootloader.cpp to TWRP and removed AOSP fstab parsing from startup --- Android.mk | 2 +- partition.cpp | 27 +++++-- partitions.hpp | 6 +- recovery.cpp | 2 +- twbootloader.cpp | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++ twrp-functions.cpp | 12 +++- twrp-functions.hpp | 1 + 7 files changed, 241 insertions(+), 13 deletions(-) create mode 100644 twbootloader.cpp diff --git a/Android.mk b/Android.mk index 4fd182dfb..e13af68be 100644 --- a/Android.mk +++ b/Android.mk @@ -20,7 +20,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ recovery.cpp \ - bootloader.cpp \ + twbootloader.cpp \ install.cpp \ roots.cpp \ ui.cpp \ diff --git a/partition.cpp b/partition.cpp index a9d50917f..6f2130911 100644 --- a/partition.cpp +++ b/partition.cpp @@ -101,9 +101,8 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) { if (full_line[index] <= 32) full_line[index] = '\0'; } - string mount_pt(full_line); - Mount_Point = mount_pt; - LOGI("Processing '%s'\n", mount_pt); + Mount_Point = full_line; + LOGI("Processing '%s'\n", Mount_Point.c_str()); Backup_Path = Mount_Point; index = Mount_Point.size(); while (index < line_len) { @@ -1076,7 +1075,7 @@ bool TWPartition::Backup_Tar(string backup_folder) { string Full_FileName, Split_FileName, Tar_Args, Command; int use_compression, index, backup_count; struct stat st; - unsigned long long total_bsize = 0; + unsigned long long total_bsize = 0, file_size; if (!Mount(true)) return false; @@ -1110,11 +1109,12 @@ bool TWPartition::Backup_Tar(string backup_folder) { ui_print("Backup archive %i of %i...\n", (index + 1), backup_count); system(Command.c_str()); // sending backup command formed earlier above - if (stat(Full_FileName.c_str(), &st) != 0 || st.st_size == 0) { - LOGE("File size is zero bytes. Aborting...\n\n"); // oh noes! file size is 0, abort! abort! + file_size = TWFunc::Get_File_Size(Full_FileName); + if (file_size == 0) { + LOGE("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str()); // oh noes! file size is 0, abort! abort! return false; } - total_bsize += st.st_size; + total_bsize += file_size; } ui_print(" * Total size: %llu bytes.\n", total_bsize); system("cd /tmp && rm -rf list"); @@ -1126,6 +1126,10 @@ bool TWPartition::Backup_Tar(string backup_folder) { Command = "cd " + Backup_Path + " && tar " + Tar_Args + " -f '" + Full_FileName + "' ./*"; LOGI("Backup command: '%s'\n", Command.c_str()); system(Command.c_str()); + if (TWFunc::Get_File_Size(Full_FileName) == 0) { + LOGE("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str()); + return false; + } } return true; } @@ -1146,6 +1150,10 @@ bool TWPartition::Backup_DD(string backup_folder) { Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'"; LOGI("Backup command: '%s'\n", Command.c_str()); system(Command.c_str()); + if (TWFunc::Get_File_Size(Full_FileName) != Backup_Size) { + LOGE("Backup file size %lu for '%s' is does not match backup size %llu.\n", TWFunc::Get_File_Size(Full_FileName), Full_FileName.c_str(), Backup_Size); + return false; + } return true; } @@ -1165,6 +1173,11 @@ bool TWPartition::Backup_Dump_Image(string backup_folder) { Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'"; LOGI("Backup command: '%s'\n", Command.c_str()); system(Command.c_str()); + if (TWFunc::Get_File_Size(Full_FileName) == 0) { + // Actual size may not match backup size due to bad blocks on MTD devices so just check for 0 bytes + LOGE("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str()); + return false; + } return true; } diff --git a/partitions.hpp b/partitions.hpp index c04f0cff9..5bd1197cc 100644 --- a/partitions.hpp +++ b/partitions.hpp @@ -61,6 +61,10 @@ public: virtual bool Update_Size(bool Display_Error); // Updates size information virtual void Recreate_Media_Folder(); // Recreates the /data/media folder +public: + string Current_File_System; // Current file system + string Actual_Block_Device; // Actual block device (one of primary, alternate, or decrypted) + protected: bool Process_Fstab_Line(string Line, bool Display_Error); // Processes a fstab line void Find_Actual_Block_Device(); // Determines the correct block device and stores it in Actual_Block_Device @@ -77,7 +81,6 @@ protected: string Symlink_Mount_Point; // /sdcard could be the symlink mount point for /data/media string Mount_Point; // Mount point for this partition (e.g. /system or /data) string Backup_Path; // Path for backup - string Actual_Block_Device; // Actual block device (one of primary, alternate, or decrypted) string Primary_Block_Device; // Block device (e.g. /dev/block/mmcblk1p1) string Alternate_Block_Device; // Alternate block device (e.g. /dev/block/mmcblk1) string Decrypted_Block_Device; // Decrypted block device available after decryption @@ -100,7 +103,6 @@ protected: bool Has_Android_Secure; // Indicates the presence of .android_secure on this partition bool Is_Storage; // Indicates if this partition is used for storage for backup, restore, and installing zips string Storage_Path; // Indicates the path to the storage -- root indicates mount point, media/ indicates e.g. /data/media - string Current_File_System; // Current file system string Fstab_File_System; // File system from the recovery.fstab int Format_Block_Size; // Block size for formatting diff --git a/recovery.cpp b/recovery.cpp index 8cf31069e..d6ed79c7e 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -803,7 +803,7 @@ main(int argc, char **argv) { //ui->Init(); //ui->SetBackground(RecoveryUI::NONE); - load_volume_table(); + //load_volume_table(); // Load default values to set DataManager constants and handle ifdefs DataManager_LoadDefaults(); diff --git a/twbootloader.cpp b/twbootloader.cpp new file mode 100644 index 000000000..905c78ed0 --- /dev/null +++ b/twbootloader.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bootloader.h" +#include "common.h" +extern "C" { +#include "mtdutils/mtdutils.h" +} + +#include +#include +#include +#include +#include +#include "partitions.hpp" + +static int get_bootloader_message_mtd(struct bootloader_message *out, const TWPartition* Partition); +static int set_bootloader_message_mtd(const struct bootloader_message *in, const TWPartition* Partition); +static int get_bootloader_message_block(struct bootloader_message *out, const TWPartition* Partition); +static int set_bootloader_message_block(const struct bootloader_message *in, const TWPartition* Partition); + +int get_bootloader_message(struct bootloader_message *out) { + TWPartition* Part = PartitionManager.Find_Partition_By_Path("/misc"); + if (Part == NULL) { + //LOGE("Cannot load volume /misc!\n"); + return -1; + } + if (Part->Current_File_System == "mtd") { + return get_bootloader_message_mtd(out, Part); + } else if (Part->Current_File_System == "emmc") { + return get_bootloader_message_block(out, Part); + } + LOGE("unknown misc partition fs_type \"%s\"\n", Part->Current_File_System.c_str()); + return -1; +} + +int set_bootloader_message(const struct bootloader_message *in) { + TWPartition* Part = PartitionManager.Find_Partition_By_Path("/misc"); + if (Part == NULL) { + //LOGE("Cannot load volume /misc!\n"); + return -1; + } + if (Part->Current_File_System == "mtd") { + return set_bootloader_message_mtd(in, Part); + } else if (Part->Current_File_System == "emmc") { + return set_bootloader_message_block(in, Part); + } + LOGE("unknown misc partition fs_type \"%s\"\n", Part->Current_File_System.c_str()); + return -1; +} + +// ------------------------------ +// for misc partitions on MTD +// ------------------------------ + +static const int MISC_PAGES = 3; // number of pages to save +static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page + +static int get_bootloader_message_mtd(struct bootloader_message *out, + const TWPartition* Partition) { + size_t write_size; + mtd_scan_partitions(); + const MtdPartition *part = mtd_find_partition_by_name(Partition->Actual_Block_Device.c_str()); + if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { + LOGE("Can't find %s\n", Partition->Actual_Block_Device.c_str()); + return -1; + } + + MtdReadContext *read = mtd_read_partition(part); + if (read == NULL) { + LOGE("Can't open %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + + const ssize_t size = write_size * MISC_PAGES; + char data[size]; + ssize_t r = mtd_read_data(read, data, size); + if (r != size) LOGE("Can't read %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + mtd_read_close(read); + if (r != size) return -1; + + memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); + return 0; +} +static int set_bootloader_message_mtd(const struct bootloader_message *in, + const TWPartition* Partition) { + size_t write_size; + mtd_scan_partitions(); + const MtdPartition *part = mtd_find_partition_by_name(Partition->Actual_Block_Device.c_str()); + if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { + LOGE("Can't find %s\n", Partition->Actual_Block_Device.c_str()); + return -1; + } + + MtdReadContext *read = mtd_read_partition(part); + if (read == NULL) { + LOGE("Can't open %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + + ssize_t size = write_size * MISC_PAGES; + char data[size]; + ssize_t r = mtd_read_data(read, data, size); + if (r != size) LOGE("Can't read %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + mtd_read_close(read); + if (r != size) return -1; + + memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); + + MtdWriteContext *write = mtd_write_partition(part); + if (write == NULL) { + LOGE("Can't open %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + if (mtd_write_data(write, data, size) != size) { + LOGE("Can't write %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + mtd_write_close(write); + return -1; + } + if (mtd_write_close(write)) { + LOGE("Can't finish %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + + LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); + return 0; +} + + +// ------------------------------------ +// for misc partitions on block devices +// ------------------------------------ + +static void wait_for_device(const char* fn) { + int tries = 0; + int ret; + struct stat buf; + do { + ++tries; + ret = stat(fn, &buf); + if (ret) { + printf("stat %s try %d: %s\n", fn, tries, strerror(errno)); + sleep(1); + } + } while (ret && tries < 10); + if (ret) { + printf("failed to stat %s\n", fn); + } +} + +static int get_bootloader_message_block(struct bootloader_message *out, + const TWPartition* Partition) { + wait_for_device(Partition->Actual_Block_Device.c_str()); + FILE* f = fopen(Partition->Actual_Block_Device.c_str(), "rb"); + if (f == NULL) { + LOGE("Can't open %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + struct bootloader_message temp; + int count = fread(&temp, sizeof(temp), 1, f); + if (count != 1) { + LOGE("Failed reading %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + if (fclose(f) != 0) { + LOGE("Failed closing %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + memcpy(out, &temp, sizeof(temp)); + return 0; +} + +static int set_bootloader_message_block(const struct bootloader_message *in, + const TWPartition* Partition) { + wait_for_device(Partition->Actual_Block_Device.c_str()); + FILE* f = fopen(Partition->Actual_Block_Device.c_str(), "wb"); + if (f == NULL) { + LOGE("Can't open %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + int count = fwrite(in, sizeof(*in), 1, f); + if (count != 1) { + LOGE("Failed writing %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + if (fclose(f) != 0) { + LOGE("Failed closing %s\n(%s)\n", Partition->Actual_Block_Device.c_str(), strerror(errno)); + return -1; + } + return 0; +} diff --git a/twrp-functions.cpp b/twrp-functions.cpp index a681de280..066e6e57b 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -221,9 +221,9 @@ unsigned long long TWFunc::Get_Folder_Size(string Path, bool Display_Error) { bool TWFunc::Path_Exists(string Path) { // Check to see if the Path exists - struct statfs st; + struct stat st; - if (statfs(Path.c_str(), &st) != 0) + if (stat(Path.c_str(), &st) != 0) return false; else return true; @@ -249,4 +249,12 @@ void TWFunc::GUI_Operation_Text(string Read_Value, string Partition_Name, string DataManager::SetValue("tw_operation", Display_Text); 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; } \ No newline at end of file diff --git a/twrp-functions.hpp b/twrp-functions.hpp index e4af7eeae..aebd7c3ef 100644 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -22,6 +22,7 @@ public: 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 }; -- cgit v1.2.3