summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--data.cpp2
-rw-r--r--gui/action.cpp54
-rw-r--r--gui/devices/1080x1920/res/ui.xml1
-rw-r--r--gui/devices/320x320/res/ui.xml3
-rw-r--r--gui/devices/480x800/res/ui.xml1
-rw-r--r--gui/devices/landscape/res/landscape.xml98
-rw-r--r--gui/devices/portrait/res/portrait.xml113
-rw-r--r--gui/devices/watch/res/watch.xml111
-rw-r--r--gui/objects.hpp2
-rw-r--r--partition.cpp56
-rw-r--r--partitionmanager.cpp6
-rw-r--r--partitions.hpp3
-rw-r--r--twrp.cpp16
13 files changed, 459 insertions, 7 deletions
diff --git a/data.cpp b/data.cpp
index 0ce4ddc3c..eb8b55341 100644
--- a/data.cpp
+++ b/data.cpp
@@ -852,6 +852,8 @@ void DataManager::SetDefaultValues()
mConstValues.insert(make_pair("tw_has_mtp", "0"));
mConstValues.insert(make_pair("tw_mtp_enabled", "0"));
#endif
+ mValues.insert(make_pair("tw_mount_system_ro", make_pair("1", 1)));
+ mValues.insert(make_pair("tw_never_show_system_ro_page", make_pair("0", 1)));
pthread_mutex_unlock(&m_valuesLock);
}
diff --git a/gui/action.cpp b/gui/action.cpp
index 342551247..7ecd0b46a 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -196,6 +196,8 @@ GUIAction::GUIAction(xml_node<>* node)
ADD_ACTION(startmtp);
ADD_ACTION(stopmtp);
ADD_ACTION(cancelbackup);
+ ADD_ACTION(checkpartitionlifetimewrites);
+ ADD_ACTION(mountsystemtoggle);
// remember actions that run in the caller thread
for (mapFunc::const_iterator it = mf.begin(); it != mf.end(); ++it)
@@ -1737,3 +1739,55 @@ int GUIAction::getKeyByName(std::string key)
return atol(key.c_str());
}
+
+int GUIAction::checkpartitionlifetimewrites(std::string arg)
+{
+ int op_status = 0;
+ TWPartition* sys = PartitionManager.Find_Partition_By_Path(arg);
+
+ operation_start("Check Partition Lifetime Writes");
+ if (sys) {
+ if (sys->Check_Lifetime_Writes() != 0)
+ DataManager::SetValue("tw_lifetime_writes", 1);
+ else
+ DataManager::SetValue("tw_lifetime_writes", 0);
+ op_status = 0; // success
+ } else {
+ DataManager::SetValue("tw_lifetime_writes", 1);
+ op_status = 1; // fail
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::mountsystemtoggle(std::string arg)
+{
+ int op_status = 0;
+ bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
+
+ operation_start("Toggle System Mount");
+ if (!PartitionManager.UnMount_By_Path("/system", true)) {
+ op_status = 1; // fail
+ } else {
+ TWPartition* Part = PartitionManager.Find_Partition_By_Path("/system");
+ if (Part) {
+ if (DataManager::GetIntValue("tw_mount_system_ro")) {
+ DataManager::SetValue("tw_mount_system_ro", 0);
+ Part->Change_Mount_Read_Only(false);
+ } else {
+ DataManager::SetValue("tw_mount_system_ro", 1);
+ Part->Change_Mount_Read_Only(true);
+ }
+ if (remount_system) {
+ Part->Mount(true);
+ }
+ op_status = 0; // success
+ } else {
+ op_status = 1; // fail
+ }
+ }
+
+ operation_end(op_status);
+ return 0;
+}
diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml
index 3135a03dc..a611d0582 100644
--- a/gui/devices/1080x1920/res/ui.xml
+++ b/gui/devices/1080x1920/res/ui.xml
@@ -86,6 +86,7 @@
<variable name="tz_selected_y" value="240" />
<variable name="tz_set_y" value="1500" />
<variable name="tz_current_y" value="1425" />
+ <variable name="system_ro_y" value="1770" />
<variable name="col_progressbar_x" value="351" />
<variable name="row_progressbar_y" value="1650" />
<variable name="col1_medium_x" value="10" />
diff --git a/gui/devices/320x320/res/ui.xml b/gui/devices/320x320/res/ui.xml
index 5495b7717..1dec40504 100644
--- a/gui/devices/320x320/res/ui.xml
+++ b/gui/devices/320x320/res/ui.xml
@@ -174,6 +174,7 @@
<variable name="row_offset_medium_y" value="206" />
<variable name="tz_set_y" value="271" />
<variable name="tz_current_y" value="249" />
+ <variable name="system_ro_y" value="216" />
<variable name="button_fill_color" value="#303030" />
<variable name="button_fill_full_width" value="308" />
<variable name="button_fill_main_width" value="150" />
@@ -189,7 +190,7 @@
<variable name="backup_button_row1" value="214" />
<variable name="backup_button_row2" value="242" />
<variable name="mount_list_height" value="190" />
- <variable name="mount_storage_row" value="200" />
+ <variable name="mount_storage_row" value="193" />
<variable name="storage_list_height" value="134" />
<variable name="wipe_list_height" value="216" />
<variable name="wipe_button_y" value="170" />
diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml
index 3c320a7eb..984454109 100644
--- a/gui/devices/480x800/res/ui.xml
+++ b/gui/devices/480x800/res/ui.xml
@@ -82,6 +82,7 @@
<variable name="tz_selected_y" value="110" />
<variable name="tz_set_y" value="580" />
<variable name="tz_current_y" value="730" />
+ <variable name="system_ro_y" value="550" />
<variable name="col_progressbar_x" value="114" />
<variable name="row_progressbar_y" value="720" />
<variable name="col1_medium_x" value="10" />
diff --git a/gui/devices/landscape/res/landscape.xml b/gui/devices/landscape/res/landscape.xml
index 25b9b17e7..12c66290b 100644
--- a/gui/devices/landscape/res/landscape.xml
+++ b/gui/devices/landscape/res/landscape.xml
@@ -989,6 +989,27 @@
</actions>
</object>
+ <object type="button">
+ <placement x="%col3_x%" y="%row10_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row10_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
<object type="action">
<touch key="home" />
<action function="page">main</action>
@@ -1035,6 +1056,31 @@
<object type="template" name="footer" />
</page>
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="1" />
+ </conditions>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
<page name="wipe">
<object type="template" name="header" />
@@ -3596,5 +3642,57 @@
</actions>
</object>
</page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>TWRP has detected an unmodified system partition.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row7_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
</pages>
</recovery>
diff --git a/gui/devices/portrait/res/portrait.xml b/gui/devices/portrait/res/portrait.xml
index bd235981d..997da9d23 100644
--- a/gui/devices/portrait/res/portrait.xml
+++ b/gui/devices/portrait/res/portrait.xml
@@ -2105,6 +2105,27 @@
<action function="page">decrypt</action>
</object>
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
<object type="action">
<touch key="home" />
<action function="page">main</action>
@@ -2161,6 +2182,31 @@
</object>
</page>
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="1" />
+ </conditions>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
<page name="reboot">
<object type="template" name="header" />
@@ -3607,5 +3653,72 @@
</actions>
</object>
</page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>TWRP has detected an unmodified system partition.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row7_text_y%" placement="5" />
+ <text>modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row8_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row10_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
</pages>
</recovery>
diff --git a/gui/devices/watch/res/watch.xml b/gui/devices/watch/res/watch.xml
index 872c47b6b..f0f383dcb 100644
--- a/gui/devices/watch/res/watch.xml
+++ b/gui/devices/watch/res/watch.xml
@@ -2113,6 +2113,27 @@
<action function="page">decrypt</action>
</object>
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
<object type="action">
<touch key="home" />
<action function="page">main</action>
@@ -2168,6 +2189,31 @@
</object>
</page>
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="1" />
+ </conditions>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_lifetime_writes" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
<page name="reboot">
<object type="template" name="header" />
@@ -3596,5 +3642,70 @@
</actions>
</object>
</page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>TWRP has detected an unmodified system partition.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row7_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row9_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="set">tw_mount_system_ro=0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+ </page>
</pages>
</recovery>
diff --git a/gui/objects.hpp b/gui/objects.hpp
index e70053e3b..ee0f08b8f 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -359,6 +359,8 @@ protected:
int stopmtp(std::string arg);
int flashimage(std::string arg);
int cancelbackup(std::string arg);
+ int checkpartitionlifetimewrites(std::string arg);
+ int mountsystemtoggle(std::string arg);
int simulate;
};
diff --git a/partition.cpp b/partition.cpp
index 248ee9bc2..2f9f41a69 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -155,6 +155,7 @@ TWPartition::TWPartition() {
Crypto_Key_Location = "footer";
MTP_Storage_ID = 0;
Can_Flash_Img = false;
+ Mount_Read_Only = false;
}
TWPartition::~TWPartition(void) {
@@ -258,6 +259,7 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
Storage_Name = Display_Name;
Wipe_Available_in_GUI = true;
Can_Be_Backed_Up = true;
+ Mount_Read_Only = true;
} else if (Mount_Point == "/data") {
UnMount(false); // added in case /data is mounted as tmpfs for qcom hardware decrypt
Display_Name = "Data";
@@ -390,6 +392,11 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
Display_Name = "Recovery";
Backup_Display_Name = Display_Name;
Can_Flash_Img = true;
+ } else if (Mount_Point == "/system_image") {
+ Display_Name = "System Image";
+ Backup_Display_Name = Display_Name;
+ Can_Flash_Img = false;
+ Can_Be_Backed_Up = true;
}
}
@@ -936,6 +943,7 @@ bool TWPartition::Is_Mounted(void) {
bool TWPartition::Mount(bool Display_Error) {
int exfat_mounted = 0;
+ unsigned long flags = Mount_Flags;
if (Is_Mounted()) {
return true;
@@ -964,9 +972,15 @@ bool TWPartition::Mount(bool Display_Error) {
#endif
}
}
+
+ if (Mount_Read_Only)
+ flags |= MS_RDONLY;
+
if (Fstab_File_System == "yaffs2") {
// mount an MTD partition as a YAFFS2 filesystem.
- const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
+ flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
+ if (Mount_Read_Only)
+ flags |= MS_RDONLY;
if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
if (Display_Error)
@@ -1008,8 +1022,8 @@ bool TWPartition::Mount(bool Display_Error) {
mount_fs = "texfat";
if (!exfat_mounted &&
- mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), Mount_Flags, Mount_Options.c_str()) != 0 &&
- mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), Mount_Flags, NULL) != 0) {
+ mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, Mount_Options.c_str()) != 0 &&
+ mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, NULL) != 0) {
#ifdef TW_NO_EXFAT_FUSE
if (Current_File_System == "exfat") {
LOGINFO("Mounting exfat failed, trying vfat...\n");
@@ -1018,7 +1032,7 @@ bool TWPartition::Mount(bool Display_Error) {
LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
else
LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
- LOGINFO("Actual block device: '%s', current file system: '%s', flags: 0x%8x, options: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str(), Mount_Flags, Mount_Options.c_str());
+ LOGINFO("Actual block device: '%s', current file system: '%s', flags: 0x%8x, options: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str(), flags, Mount_Options.c_str());
return false;
}
} else {
@@ -2138,3 +2152,37 @@ bool TWPartition::Flash_Image_FI(string Filename) {
TWFunc::Exec_Cmd(Command);
return true;
}
+
+void TWPartition::Change_Mount_Read_Only(bool new_value) {
+ Mount_Read_Only = new_value;
+}
+
+int TWPartition::Check_Lifetime_Writes() {
+ bool original_read_only = Mount_Read_Only;
+ int ret = 1;
+
+ Mount_Read_Only = true;
+ if (Mount(false)) {
+ Find_Actual_Block_Device();
+ string block = basename(Actual_Block_Device.c_str());
+ string file = "/sys/fs/" + Current_File_System + "/" + block + "/lifetime_write_kbytes";
+ string result;
+ if (TWFunc::Path_Exists(file)) {
+ if (TWFunc::read_file(file, result) != 0) {
+ LOGINFO("Check_Lifetime_Writes of '%s' failed to read_file\n", file.c_str());
+ } else {
+ LOGINFO("Check_Lifetime_Writes result: '%s'\n", result.c_str());
+ if (result == "0") {
+ ret = 0;
+ }
+ }
+ } else {
+ LOGINFO("Check_Lifetime_Writes file does not exist '%s'\n", file.c_str());
+ }
+ UnMount(true);
+ } else {
+ LOGINFO("Check_Lifetime_Writes failed to mount '%s'\n", Mount_Point.c_str());
+ }
+ Mount_Read_Only = original_read_only;
+ return ret;
+}
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index ffc17c3a4..055f73697 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -880,9 +880,13 @@ int TWPartitionManager::Run_Restore(string Restore_Name) {
restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
restore_part = Find_Partition_By_Path(restore_path);
if (restore_part != NULL) {
- partition_count++;
+ if (restore_part->Mount_Read_Only) {
+ LOGERR("Cannot restore %s -- mounted read only.\n", restore_part->Backup_Display_Name.c_str());
+ return false;
+ }
if (check_md5 > 0 && !restore_part->Check_MD5(Restore_Name))
return false;
+ partition_count++;
total_restore_size += restore_part->Get_Restore_Size(Restore_Name);
if (restore_part->Has_SubPartition) {
std::vector<TWPartition*>::iterator subpart;
diff --git a/partitions.hpp b/partitions.hpp
index f74fac9a1..1489a8ec2 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -70,6 +70,8 @@ public:
bool Update_Size(bool Display_Error); // Updates size information
void Recreate_Media_Folder(); // Recreates the /data/media folder
bool Flash_Image(string Filename); // Flashes an image to the partition
+ void Change_Mount_Read_Only(bool new_value); // Changes Mount_Read_Only to new_value
+ int Check_Lifetime_Writes();
public:
string Current_File_System; // Current file system
@@ -167,6 +169,7 @@ private:
bool Ignore_Blkid; // Ignore blkid results due to superblocks lying to us on certain devices / partitions
bool Retain_Layout_Version; // Retains the .layout_version file during a wipe (needed on devices like Sony Xperia T where /data and /data/media are separate partitions)
bool Can_Flash_Img; // Indicates if this partition can have images flashed to it via the GUI
+ bool Mount_Read_Only; // Only mount this partition as read-only
friend class TWPartitionManager;
friend class DataManager;
diff --git a/twrp.cpp b/twrp.cpp
index 0c012d7ec..b7fc9815d 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -332,13 +332,27 @@ int main(int argc, char **argv) {
PartitionManager.Disable_MTP();
#endif
+ // Check if system has never been changed
+ if (DataManager::GetIntValue("tw_mount_system_ro") != 0 && DataManager::GetIntValue("tw_never_show_system_ro_page") == 0) {
+ TWPartition* sys = PartitionManager.Find_Partition_By_Path("/system");
+ if (sys && sys->Check_Lifetime_Writes() == 0) {
+ LOGINFO("System writes is 0, show system_readonly page\n");
+ DataManager::SetValue("tw_back", "main");
+ if (gui_startPage("system_readonly", 1, 1) != 0) {
+ LOGERR("Failed to start system_readonly GUI page.\n");
+ }
+ } else {
+ DataManager::SetValue("tw_mount_system_ro", 0);
+ }
+ }
+
// Launch the main GUI
gui_start();
// Disable flashing of stock recovery
TWFunc::Disable_Stock_Recovery_Replace();
// Check for su to see if the device is rooted or not
- if (PartitionManager.Mount_By_Path("/system", false)) {
+ if (PartitionManager.Mount_By_Path("/system", false) && DataManager::GetIntValue("tw_mount_system_ro") == 0) {
if (TWFunc::Path_Exists("/supersu/su") && !TWFunc::Path_Exists("/system/bin/su") && !TWFunc::Path_Exists("/system/xbin/su") && !TWFunc::Path_Exists("/system/bin/.ext/.su")) {
// Device doesn't have su installed
DataManager::SetValue("tw_busy", 1);