blob: 12d4ad0da6fb182d9efaa3aad80b1b7774f86cd4 [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
Ethan Yonker472f5062016-02-25 13:47:30 -06002 Copyright 2013 to 2016 TeamWin
Dees Troy3be70a82013-10-22 14:25:12 +00003 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/stat.h>
23#include <sys/vfs.h>
Dees_Troy5bf43922012-09-07 16:07:55 -040024#include <sys/mount.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040025#include <unistd.h>
Dees_Troy51127312012-09-08 13:08:49 -040026#include <dirent.h>
thatf54e5392016-01-29 22:04:43 +010027#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050028#include <iostream>
29#include <sstream>
Ethan Yonker66a19492015-12-10 10:19:45 -060030#include <sys/param.h>
Ethan Yonker472f5062016-02-25 13:47:30 -060031#include <fcntl.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040032
Dees_Troy657c3092012-09-10 20:32:10 -040033#ifdef TW_INCLUDE_CRYPTO
34 #include "cutils/properties.h"
35#endif
36
bigbiff7b4c7a62015-01-01 19:44:14 -050037#include "libblkid/include/blkid.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040038#include "variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000039#include "twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040040#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040041#include "data.hpp"
Dees_Troy43d8b002012-09-17 16:00:01 -040042#include "twrp-functions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050043#include "twrpDigest.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050044#include "twrpTar.hpp"
bigbiff bigbiff34684ff2013-12-01 21:03:45 -050045#include "twrpDU.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050046#include "infomanager.hpp"
Ethan Yonker4b94cfd2014-12-11 10:00:45 -060047#include "set_metadata.h"
Ethan Yonker74db1572015-10-28 12:44:49 -050048#include "gui/gui.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040049extern "C" {
Dees_Troy38bd7602012-09-14 13:33:53 -040050 #include "mtdutils/mtdutils.h"
51 #include "mtdutils/mounts.h"
Dees_Troya95f55c2013-08-17 13:14:43 +000052#ifdef USE_EXT4
53 #include "make_ext4fs.h"
54#endif
Ethan Yonker71413f42014-02-26 13:36:08 -060055
56#ifdef TW_INCLUDE_CRYPTO
Ethan Yonker253368a2014-11-25 15:00:52 -060057 #include "crypto/lollipop/cryptfs.h"
Ethan Yonker66a19492015-12-10 10:19:45 -060058 #include "gpt/gpt.h"
Ethan Yonkerbc85b632015-08-09 12:48:14 -050059#else
60 #define CRYPT_FOOTER_OFFSET 0x4000
Ethan Yonker71413f42014-02-26 13:36:08 -060061#endif
Dees_Troy5bf43922012-09-07 16:07:55 -040062}
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040063#ifdef HAVE_SELINUX
64#include "selinux/selinux.h"
Ethan Yonkerf27497f2014-02-09 11:48:33 -060065#include <selinux/label.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040066#endif
Dees Troy4159aed2014-02-28 17:24:43 +000067#ifdef HAVE_CAPABILITIES
68#include <sys/capability.h>
69#include <sys/xattr.h>
70#include <linux/xattr.h>
71#endif
HashBanged974bb2016-01-30 14:20:09 -050072#include <sparse_format.h>
Ethan Yonker472f5062016-02-25 13:47:30 -060073#include "progresstracking.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040074
bigbiff bigbiff9c754052013-01-09 09:09:08 -050075using namespace std;
76
Dees_Troya95f55c2013-08-17 13:14:43 +000077extern struct selabel_handle *selinux_handle;
Ethan Yonker6277c792014-09-15 14:54:30 -050078extern bool datamedia;
Dees_Troya95f55c2013-08-17 13:14:43 +000079
Hashcode62bd9e02013-11-19 21:59:42 -080080struct flag_list {
81 const char *name;
82 unsigned flag;
83};
84
85static struct flag_list mount_flags[] = {
86 { "noatime", MS_NOATIME },
87 { "noexec", MS_NOEXEC },
88 { "nosuid", MS_NOSUID },
89 { "nodev", MS_NODEV },
90 { "nodiratime", MS_NODIRATIME },
91 { "ro", MS_RDONLY },
92 { "rw", 0 },
93 { "remount", MS_REMOUNT },
94 { "bind", MS_BIND },
95 { "rec", MS_REC },
Dees Troyc4bc30e2014-02-03 15:04:19 +000096#ifdef MS_UNBINDABLE
Hashcode62bd9e02013-11-19 21:59:42 -080097 { "unbindable", MS_UNBINDABLE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000098#endif
99#ifdef MS_PRIVATE
Hashcode62bd9e02013-11-19 21:59:42 -0800100 { "private", MS_PRIVATE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000101#endif
102#ifdef MS_SLAVE
Hashcode62bd9e02013-11-19 21:59:42 -0800103 { "slave", MS_SLAVE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000104#endif
105#ifdef MS_SHARED
Hashcode62bd9e02013-11-19 21:59:42 -0800106 { "shared", MS_SHARED },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000107#endif
Hashcode62bd9e02013-11-19 21:59:42 -0800108 { "sync", MS_SYNCHRONOUS },
109 { "defaults", 0 },
110 { 0, 0 },
111};
112
that9e0593e2014-10-08 00:01:24 +0200113TWPartition::TWPartition() {
Dees_Troy51a0e822012-09-05 15:24:24 -0400114 Can_Be_Mounted = false;
115 Can_Be_Wiped = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500116 Can_Be_Backed_Up = false;
Vojtech Bocek1dc30982013-08-30 21:49:30 +0200117 Use_Rm_Rf = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400118 Wipe_During_Factory_Reset = false;
119 Wipe_Available_in_GUI = false;
120 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -0400121 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400122 SubPartition_Of = "";
123 Symlink_Path = "";
124 Symlink_Mount_Point = "";
125 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -0400126 Backup_Path = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400127 Actual_Block_Device = "";
128 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400129 Alternate_Block_Device = "";
130 Removable = false;
131 Is_Present = false;
132 Length = 0;
133 Size = 0;
134 Used = 0;
135 Free = 0;
136 Backup_Size = 0;
137 Can_Be_Encrypted = false;
138 Is_Encrypted = false;
139 Is_Decrypted = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600140 Mount_To_Decrypt = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400141 Decrypted_Block_Device = "";
142 Display_Name = "";
Dees_Troya13d74f2013-03-24 08:54:55 -0500143 Backup_Display_Name = "";
144 Storage_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400145 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -0400146 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400147 MTD_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400148 Backup_Method = NONE;
Dees_Troy83bd4832013-05-04 12:39:56 +0000149 Can_Encrypt_Backup = false;
150 Use_Userdata_Encryption = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400151 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -0400152 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400153 Is_Storage = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500154 Is_Settings_Storage = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400155 Storage_Path = "";
156 Current_File_System = "";
157 Fstab_File_System = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800158 Mount_Flags = 0;
159 Mount_Options = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400160 Format_Block_Size = 0;
Dees_Troy68cab492012-12-12 19:29:35 +0000161 Ignore_Blkid = false;
Dees_Troy16c2b312013-01-15 16:51:18 +0000162 Retain_Layout_Version = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600163 Crypto_Key_Location = "footer";
Ethan Yonker726a0202014-12-16 20:01:38 -0600164 MTP_Storage_ID = 0;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600165 Can_Flash_Img = false;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500166 Mount_Read_Only = false;
Ethan Yonker66a19492015-12-10 10:19:45 -0600167 Is_Adopted_Storage = false;
168 Adopted_GUID = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400169}
170
171TWPartition::~TWPartition(void) {
172 // Do nothing
173}
174
Dees_Troy5bf43922012-09-07 16:07:55 -0400175bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
176 char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH];
177 int line_len = Line.size(), index = 0, item_index = 0;
178 char* ptr;
Dees_Troy51127312012-09-08 13:08:49 -0400179 string Flags;
Dees_Troy5bf43922012-09-07 16:07:55 -0400180 strncpy(full_line, Line.c_str(), line_len);
Dees_Troya13d74f2013-03-24 08:54:55 -0500181 bool skip = false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400182
Dees_Troy51127312012-09-08 13:08:49 -0400183 for (index = 0; index < line_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500184 if (full_line[index] == 34)
185 skip = !skip;
186 if (!skip && full_line[index] <= 32)
Dees_Troy5bf43922012-09-07 16:07:55 -0400187 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400188 }
Dees_Troy7c2dec82012-09-26 09:49:14 -0400189 Mount_Point = full_line;
Dees_Troy2673cec2013-04-02 20:22:16 +0000190 LOGINFO("Processing '%s'\n", Mount_Point.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -0400191 Backup_Path = Mount_Point;
Dees_Troya13d74f2013-03-24 08:54:55 -0500192 Storage_Path = Mount_Point;
Dees_Troy70737fa2013-04-08 13:19:20 +0000193 Display_Name = full_line + 1;
194 Backup_Display_Name = Display_Name;
195 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400196 index = Mount_Point.size();
197 while (index < line_len) {
198 while (index < line_len && full_line[index] == '\0')
199 index++;
200 if (index >= line_len)
201 continue;
202 ptr = full_line + index;
203 if (item_index == 0) {
204 // File System
205 Fstab_File_System = ptr;
206 Current_File_System = ptr;
207 item_index++;
208 } else if (item_index == 1) {
209 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400210 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
Dees_Troy094207a2012-09-26 12:00:39 -0400211 MTD_Name = ptr;
212 Find_MTD_Block_Device(MTD_Name);
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400213 } else if (Fstab_File_System == "bml") {
214 if (Mount_Point == "/boot")
215 MTD_Name = "boot";
216 else if (Mount_Point == "/recovery")
217 MTD_Name = "recovery";
218 Primary_Block_Device = ptr;
219 if (*ptr != '/')
Dees_Troy2673cec2013-04-02 20:22:16 +0000220 LOGERR("Until we get better BML support, you will have to find and provide the full block device path to the BML devices e.g. /dev/block/bml9 instead of the partition name\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400221 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400222 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000223 LOGERR("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400224 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000225 LOGINFO("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400226 return 0;
Dees_Troy38bd7602012-09-14 13:33:53 -0400227 } else {
228 Primary_Block_Device = ptr;
229 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400230 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400231 item_index++;
232 } else if (item_index > 1) {
233 if (*ptr == '/') {
234 // Alternate Block Device
235 Alternate_Block_Device = ptr;
236 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
237 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
238 // Partition length
239 ptr += 7;
240 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400241 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
242 // Custom flags, save for later so that new values aren't overwritten by defaults
243 ptr += 6;
244 Flags = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000245 Process_Flags(Flags, Display_Error);
Dees_Troy38bd7602012-09-14 13:33:53 -0400246 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
247 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400248 } else {
249 // Unhandled data
Dees_Troy2673cec2013-04-02 20:22:16 +0000250 LOGINFO("Unhandled fstab information: '%s', %i, line: '%s'\n", ptr, index, Line.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400251 }
252 }
253 while (index < line_len && full_line[index] != '\0')
254 index++;
255 }
256
257 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
258 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000259 LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400260 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000261 LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400262 return 0;
263 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400264 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400265 Setup_File_System(Display_Error);
266 if (Mount_Point == "/system") {
267 Display_Name = "System";
Dees_Troya13d74f2013-03-24 08:54:55 -0500268 Backup_Display_Name = Display_Name;
269 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400270 Wipe_Available_in_GUI = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500271 Can_Be_Backed_Up = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500272 Mount_Read_Only = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400273 } else if (Mount_Point == "/data") {
Dees Troyc657cc02015-01-16 22:48:47 +0000274 UnMount(false); // added in case /data is mounted as tmpfs for qcom hardware decrypt
Dees_Troy5bf43922012-09-07 16:07:55 -0400275 Display_Name = "Data";
Dees_Troya13d74f2013-03-24 08:54:55 -0500276 Backup_Display_Name = Display_Name;
277 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400278 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400279 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500280 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000281 Can_Encrypt_Backup = true;
282 Use_Userdata_Encryption = true;
Ethan Yonker6277c792014-09-15 14:54:30 -0500283 if (datamedia)
that9e0593e2014-10-08 00:01:24 +0200284 Setup_Data_Media();
Dees_Troy5bf43922012-09-07 16:07:55 -0400285#ifdef TW_INCLUDE_CRYPTO
286 Can_Be_Encrypted = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400287 char crypto_blkdev[255];
288 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
289 if (strcmp(crypto_blkdev, "error") != 0) {
Dees_Troy657c3092012-09-10 20:32:10 -0400290 DataManager::SetValue(TW_IS_DECRYPTED, 1);
291 Is_Encrypted = true;
292 Is_Decrypted = true;
293 Decrypted_Block_Device = crypto_blkdev;
Dees_Troy2673cec2013-04-02 20:22:16 +0000294 LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
Dees_Troy657c3092012-09-10 20:32:10 -0400295 } else if (!Mount(false)) {
Ethan Yonker71413f42014-02-26 13:36:08 -0600296 if (Is_Present) {
Ethan Yonker253368a2014-11-25 15:00:52 -0600297 set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
Ethan Yonker71413f42014-02-26 13:36:08 -0600298 if (cryptfs_check_footer() == 0) {
299 Is_Encrypted = true;
300 Is_Decrypted = false;
301 Can_Be_Mounted = false;
302 Current_File_System = "emmc";
303 Setup_Image(Display_Error);
304 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
Vojtech Bocek7e11ac52015-03-05 23:21:49 +0100305 DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
Ethan Yonker71413f42014-02-26 13:36:08 -0600306 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
307 DataManager::SetValue("tw_crypto_display", "");
308 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500309 gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
Ethan Yonker71413f42014-02-26 13:36:08 -0600310 }
311 } else {
312 LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
313 }
Gary Peck82599a82012-11-21 16:23:12 -0800314 } else {
315 // Filesystem is not encrypted and the mount
316 // succeeded, so get it back to the original
317 // unmounted state
318 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -0400319 }
Ethan Yonker6277c792014-09-15 14:54:30 -0500320 if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted)))
Dees_Troy9b21af72012-10-01 15:51:46 -0400321 Recreate_Media_Folder();
Dees_Troy9b21af72012-10-01 15:51:46 -0400322#else
Ethan Yonker6277c792014-09-15 14:54:30 -0500323 if (datamedia)
324 Recreate_Media_Folder();
Dees_Troy5bf43922012-09-07 16:07:55 -0400325#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400326 } else if (Mount_Point == "/cache") {
327 Display_Name = "Cache";
Dees_Troya13d74f2013-03-24 08:54:55 -0500328 Backup_Display_Name = Display_Name;
329 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400330 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400331 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500332 Can_Be_Backed_Up = true;
Dees_Troyce2fe772012-09-28 12:34:33 -0400333 if (Mount(false) && !TWFunc::Path_Exists("/cache/recovery/.")) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000334 LOGINFO("Recreating /cache/recovery folder.\n");
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500335 if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500336 return -1;
Dees_Troyb46a6842012-09-25 11:06:46 -0400337 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400338 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400339 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400340 Display_Name = "DataData";
Dees_Troya13d74f2013-03-24 08:54:55 -0500341 Backup_Display_Name = Display_Name;
342 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400343 Is_SubPartition = true;
344 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400345 DataManager::SetValue(TW_HAS_DATADATA, 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500346 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000347 Can_Encrypt_Backup = true;
348 Use_Userdata_Encryption = false; // This whole partition should be encrypted
Dees_Troy5bf43922012-09-07 16:07:55 -0400349 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400350 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400351 Display_Name = "SD-Ext";
Dees_Troya13d74f2013-03-24 08:54:55 -0500352 Backup_Display_Name = Display_Name;
353 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400354 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400355 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500356 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000357 Can_Encrypt_Backup = true;
358 Use_Userdata_Encryption = true;
Dees_Troy2c50e182012-09-26 20:05:28 -0400359 } else if (Mount_Point == "/boot") {
360 Display_Name = "Boot";
Dees_Troya13d74f2013-03-24 08:54:55 -0500361 Backup_Display_Name = Display_Name;
Dees_Troy2c50e182012-09-26 20:05:28 -0400362 DataManager::SetValue("tw_boot_is_mountable", 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500363 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500364 } else if (Mount_Point == "/vendor") {
365 Display_Name = "Vendor";
366 Backup_Display_Name = Display_Name;
367 Storage_Name = Display_Name;
368 Mount_Read_Only = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400369 }
370#ifdef TW_EXTERNAL_STORAGE_PATH
371 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
372 Is_Storage = true;
373 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
Dees_Troyc51f1f92012-09-20 15:32:13 -0400374 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500375 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400376#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000377 if (Mount_Point == "/sdcard" || Mount_Point == "/external_sd" || Mount_Point == "/external_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400378 Is_Storage = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400379 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500380 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400381#endif
Dees_Troyb05ddee2013-01-28 20:24:50 +0000382 }
Dees_Troy8170a922012-09-18 15:40:25 -0400383#ifdef TW_INTERNAL_STORAGE_PATH
384 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
385 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500386 Is_Settings_Storage = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400387 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troya13d74f2013-03-24 08:54:55 -0500388 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400389 }
390#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000391 if (Mount_Point == "/emmc" || Mount_Point == "/internal_sd" || Mount_Point == "/internal_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400392 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500393 Is_Settings_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500394 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400395 }
396#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400397 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400398 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400399 Setup_Image(Display_Error);
Dees_Troya13d74f2013-03-24 08:54:55 -0500400 if (Mount_Point == "/boot") {
401 Display_Name = "Boot";
402 Backup_Display_Name = Display_Name;
403 Can_Be_Backed_Up = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600404 Can_Flash_Img = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500405 } else if (Mount_Point == "/recovery") {
406 Display_Name = "Recovery";
407 Backup_Display_Name = Display_Name;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600408 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500409 } else if (Mount_Point == "/system_image") {
410 Display_Name = "System Image";
411 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500412 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500413 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500414 } else if (Mount_Point == "/vendor_image") {
415 Display_Name = "Vendor Image";
416 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500417 Can_Flash_Img = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500418 Can_Be_Backed_Up = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500419 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400420 }
421
Dees_Troy51127312012-09-08 13:08:49 -0400422 // Process any custom flags
423 if (Flags.size() > 0)
424 Process_Flags(Flags, Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400425 return true;
426}
427
Ketut Putu Kumajayabfb72b02015-08-10 16:40:55 +0200428bool TWPartition::Process_FS_Flags(string& Options, int& Flags) {
Hashcode62bd9e02013-11-19 21:59:42 -0800429 int i;
430 char *p;
431 char *savep;
432 char fs_options[250];
433
434 strlcpy(fs_options, Options.c_str(), sizeof(fs_options));
435 Options = "";
436
437 p = strtok_r(fs_options, ",", &savep);
438 while (p) {
439 /* Look for the flag "p" in the flag list "fl"
440 * If not found, the loop exits with fl[i].name being null.
441 */
442 for (i = 0; mount_flags[i].name; i++) {
443 if (strncmp(p, mount_flags[i].name, strlen(mount_flags[i].name)) == 0) {
444 Flags |= mount_flags[i].flag;
445 break;
446 }
447 }
448
449 if (!mount_flags[i].name) {
450 if (Options.size() > 0)
451 Options += ",";
452 Options += p;
453 }
454 p = strtok_r(NULL, ",", &savep);
455 }
456
457 return true;
458}
459
Dees_Troy51127312012-09-08 13:08:49 -0400460bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
461 char flags[MAX_FSTAB_LINE_LENGTH];
Dees_Troya13d74f2013-03-24 08:54:55 -0500462 int flags_len, index = 0, ptr_len;
Dees_Troy51127312012-09-08 13:08:49 -0400463 char* ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500464 bool skip = false, has_display_name = false, has_storage_name = false, has_backup_name = false;
Dees_Troy51127312012-09-08 13:08:49 -0400465
466 strcpy(flags, Flags.c_str());
467 flags_len = Flags.size();
468 for (index = 0; index < flags_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500469 if (flags[index] == 34)
470 skip = !skip;
471 if (!skip && flags[index] == ';')
Dees_Troy51127312012-09-08 13:08:49 -0400472 flags[index] = '\0';
473 }
474
475 index = 0;
476 while (index < flags_len) {
477 while (index < flags_len && flags[index] == '\0')
478 index++;
479 if (index >= flags_len)
480 continue;
481 ptr = flags + index;
Dees_Troya13d74f2013-03-24 08:54:55 -0500482 ptr_len = strlen(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400483 if (strcmp(ptr, "removable") == 0) {
484 Removable = true;
Ethan Yonker06c3f932014-02-02 22:11:14 -0600485 } else if (strncmp(ptr, "storage", 7) == 0) {
486 if (ptr_len == 7) {
Ethan Yonker06c3f932014-02-02 22:11:14 -0600487 Is_Storage = true;
488 } else if (ptr_len == 9) {
489 ptr += 9;
490 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
491 LOGINFO("storage set to true\n");
492 Is_Storage = true;
493 } else {
494 LOGINFO("storage set to false\n");
495 Is_Storage = false;
496 }
497 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500498 } else if (strcmp(ptr, "settingsstorage") == 0) {
499 Is_Storage = true;
Xueferbfce5042015-04-14 02:02:05 +0800500 Is_Settings_Storage = true;
Matt Mowerbf4efa32014-04-14 23:25:26 -0500501 } else if (strcmp(ptr, "andsec") == 0) {
502 Has_Android_Secure = true;
Dees_Troy63c8df72012-09-10 14:02:05 -0400503 } else if (strcmp(ptr, "canbewiped") == 0) {
504 Can_Be_Wiped = true;
Hashcodedabfd492013-08-29 22:45:30 -0700505 } else if (strcmp(ptr, "usermrf") == 0) {
506 Use_Rm_Rf = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500507 } else if (ptr_len > 7 && strncmp(ptr, "backup=", 7) == 0) {
508 ptr += 7;
509 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
510 Can_Be_Backed_Up = true;
511 else
512 Can_Be_Backed_Up = false;
Dees_Troy63c8df72012-09-10 14:02:05 -0400513 } else if (strcmp(ptr, "wipeingui") == 0) {
514 Can_Be_Wiped = true;
515 Wipe_Available_in_GUI = true;
516 } else if (strcmp(ptr, "wipeduringfactoryreset") == 0) {
517 Can_Be_Wiped = true;
518 Wipe_Available_in_GUI = true;
519 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500520 } else if (ptr_len > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) {
Dees_Troy2c4c26f2013-01-28 15:26:43 +0000521 ptr += 15;
Dees_Troy51127312012-09-08 13:08:49 -0400522 Is_SubPartition = true;
523 SubPartition_Of = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000524 } else if (strcmp(ptr, "ignoreblkid") == 0) {
525 Ignore_Blkid = true;
Dees_Troy16c2b312013-01-15 16:51:18 +0000526 } else if (strcmp(ptr, "retainlayoutversion") == 0) {
527 Retain_Layout_Version = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500528 } else if (ptr_len > 8 && strncmp(ptr, "symlink=", 8) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400529 ptr += 8;
530 Symlink_Path = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500531 } else if (ptr_len > 8 && strncmp(ptr, "display=", 8) == 0) {
532 has_display_name = true;
Dees_Troy51127312012-09-08 13:08:49 -0400533 ptr += 8;
Dees_Troya13d74f2013-03-24 08:54:55 -0500534 if (*ptr == '\"') ptr++;
Dees_Troy51127312012-09-08 13:08:49 -0400535 Display_Name = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500536 if (Display_Name.substr(Display_Name.size() - 1, 1) == "\"") {
537 Display_Name.resize(Display_Name.size() - 1);
538 }
539 } else if (ptr_len > 11 && strncmp(ptr, "storagename=", 11) == 0) {
540 has_storage_name = true;
541 ptr += 11;
542 if (*ptr == '\"') ptr++;
543 Storage_Name = ptr;
544 if (Storage_Name.substr(Storage_Name.size() - 1, 1) == "\"") {
545 Storage_Name.resize(Storage_Name.size() - 1);
546 }
547 } else if (ptr_len > 11 && strncmp(ptr, "backupname=", 10) == 0) {
548 has_backup_name = true;
549 ptr += 10;
550 if (*ptr == '\"') ptr++;
551 Backup_Display_Name = ptr;
552 if (Backup_Display_Name.substr(Backup_Display_Name.size() - 1, 1) == "\"") {
553 Backup_Display_Name.resize(Backup_Display_Name.size() - 1);
554 }
555 } else if (ptr_len > 10 && strncmp(ptr, "blocksize=", 10) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400556 ptr += 10;
Ethan Yonkera2719152015-05-28 09:44:41 -0500557 Format_Block_Size = (unsigned long)(atol(ptr));
Dees_Troya13d74f2013-03-24 08:54:55 -0500558 } else if (ptr_len > 7 && strncmp(ptr, "length=", 7) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400559 ptr += 7;
560 Length = atoi(ptr);
Dees_Troy83bd4832013-05-04 12:39:56 +0000561 } else if (ptr_len > 17 && strncmp(ptr, "canencryptbackup=", 17) == 0) {
562 ptr += 17;
563 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
564 Can_Encrypt_Backup = true;
565 else
566 Can_Encrypt_Backup = false;
567 } else if (ptr_len > 21 && strncmp(ptr, "userdataencryptbackup=", 21) == 0) {
568 ptr += 21;
569 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
570 Can_Encrypt_Backup = true;
571 Use_Userdata_Encryption = true;
572 } else {
573 Use_Userdata_Encryption = false;
574 }
Hashcode62bd9e02013-11-19 21:59:42 -0800575 } else if (ptr_len > 8 && strncmp(ptr, "fsflags=", 8) == 0) {
576 ptr += 8;
577 if (*ptr == '\"') ptr++;
578
579 Mount_Options = ptr;
580 if (Mount_Options.substr(Mount_Options.size() - 1, 1) == "\"") {
581 Mount_Options.resize(Mount_Options.size() - 1);
582 }
583 Process_FS_Flags(Mount_Options, Mount_Flags);
Ethan Yonker253368a2014-11-25 15:00:52 -0600584 } else if ((ptr_len > 12 && strncmp(ptr, "encryptable=", 12) == 0) || (ptr_len > 13 && strncmp(ptr, "forceencrypt=", 13) == 0)) {
585 ptr += 12;
586 if (*ptr == '=') ptr++;
587 if (*ptr == '\"') ptr++;
588
589 Crypto_Key_Location = ptr;
590 if (Crypto_Key_Location.substr(Crypto_Key_Location.size() - 1, 1) == "\"") {
591 Crypto_Key_Location.resize(Crypto_Key_Location.size() - 1);
592 }
593 } else if (ptr_len > 8 && strncmp(ptr, "mounttodecrypt", 14) == 0) {
594 Mount_To_Decrypt = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600595 } else if (strncmp(ptr, "flashimg", 8) == 0) {
596 if (ptr_len == 8) {
597 Can_Flash_Img = true;
598 } else if (ptr_len == 10) {
599 ptr += 9;
600 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
601 Can_Flash_Img = true;
602 } else {
603 Can_Flash_Img = false;
604 }
605 }
Dees_Troy51127312012-09-08 13:08:49 -0400606 } else {
607 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000608 LOGERR("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400609 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000610 LOGINFO("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400611 }
612 while (index < flags_len && flags[index] != '\0')
613 index++;
614 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500615 if (has_display_name && !has_storage_name)
616 Storage_Name = Display_Name;
617 if (!has_display_name && has_storage_name)
618 Display_Name = Storage_Name;
Dees_Troy74fb2e92013-04-15 14:35:47 +0000619 if (has_display_name && !has_backup_name && Backup_Display_Name != "Android Secure")
Dees_Troya13d74f2013-03-24 08:54:55 -0500620 Backup_Display_Name = Display_Name;
621 if (!has_display_name && has_backup_name)
622 Display_Name = Backup_Display_Name;
Dees_Troy51127312012-09-08 13:08:49 -0400623 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400624}
625
Dees_Troy5bf43922012-09-07 16:07:55 -0400626bool TWPartition::Is_File_System(string File_System) {
627 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400628 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400629 File_System == "ext4" ||
630 File_System == "vfat" ||
631 File_System == "ntfs" ||
632 File_System == "yaffs2" ||
bigbiff bigbiff3e146522012-11-14 14:32:59 -0500633 File_System == "exfat" ||
Dees_Troye5017042013-08-29 16:38:55 +0000634 File_System == "f2fs" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400635 File_System == "auto")
636 return true;
637 else
638 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400639}
640
Dees_Troy5bf43922012-09-07 16:07:55 -0400641bool TWPartition::Is_Image(string File_System) {
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400642 if (File_System == "emmc" || File_System == "mtd" || File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400643 return true;
644 else
645 return false;
646}
647
Dees_Troy51127312012-09-08 13:08:49 -0400648bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400649 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400650 if (mkdir(Path.c_str(), 0777) == -1) {
651 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -0500652 gui_msg(Msg(msg::kError, "create_folder_strerr=Can not create '{1}' folder ({2}).")(Path)(strerror(errno)));
Dees_Troy51127312012-09-08 13:08:49 -0400653 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000654 LOGINFO("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400655 return false;
656 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000657 LOGINFO("Created '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400658 return true;
659 }
660 }
661 return true;
662}
663
Dees_Troy5bf43922012-09-07 16:07:55 -0400664void TWPartition::Setup_File_System(bool Display_Error) {
665 struct statfs st;
666
667 Can_Be_Mounted = true;
668 Can_Be_Wiped = true;
669
Dees_Troy5bf43922012-09-07 16:07:55 -0400670 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400671 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400672 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
673 Backup_Name = Display_Name;
674 Backup_Method = FILES;
675}
676
677void TWPartition::Setup_Image(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400678 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
679 Backup_Name = Display_Name;
Gary Peck82599a82012-11-21 16:23:12 -0800680 if (Current_File_System == "emmc")
Dees_Troy5bf43922012-09-07 16:07:55 -0400681 Backup_Method = DD;
Gary Peck82599a82012-11-21 16:23:12 -0800682 else if (Current_File_System == "mtd" || Current_File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400683 Backup_Method = FLASH_UTILS;
684 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000685 LOGINFO("Unhandled file system '%s' on image '%s'\n", Current_File_System.c_str(), Display_Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400686 if (Find_Partition_Size()) {
687 Used = Size;
688 Backup_Size = Size;
Dees_Troy51a0e822012-09-05 15:24:24 -0400689 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400690 if (Display_Error)
Dees Troyd932ce12013-10-18 17:12:59 +0000691 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400692 else
Dees Troyd932ce12013-10-18 17:12:59 +0000693 LOGINFO("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400694 }
695}
696
Dees_Troye58d5262012-09-21 12:27:57 -0400697void TWPartition::Setup_AndSec(void) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500698 Backup_Display_Name = "Android Secure";
Dees_Troye58d5262012-09-21 12:27:57 -0400699 Backup_Name = "and-sec";
Dees_Troya13d74f2013-03-24 08:54:55 -0500700 Can_Be_Backed_Up = true;
Dees_Troye58d5262012-09-21 12:27:57 -0400701 Has_Android_Secure = true;
702 Symlink_Path = Mount_Point + "/.android_secure";
703 Symlink_Mount_Point = "/and-sec";
704 Backup_Path = Symlink_Mount_Point;
705 Make_Dir("/and-sec", true);
706 Recreate_AndSec_Folder();
Ethan Yonkerd4d10732014-02-03 15:27:52 -0600707 Mount_Storage_Retry();
Dees_Troye58d5262012-09-21 12:27:57 -0400708}
709
that9e0593e2014-10-08 00:01:24 +0200710void TWPartition::Setup_Data_Media() {
Ethan Yonker6277c792014-09-15 14:54:30 -0500711 LOGINFO("Setting up '%s' as data/media emulated storage.\n", Mount_Point.c_str());
Ethan Yonker66a19492015-12-10 10:19:45 -0600712 if (Storage_Name.empty() || Storage_Name == "Data")
713 Storage_Name = "Internal Storage";
Ethan Yonker6277c792014-09-15 14:54:30 -0500714 Has_Data_Media = true;
715 Is_Storage = true;
Ethan Yonker66a19492015-12-10 10:19:45 -0600716 Storage_Path = Mount_Point + "/media";
Ethan Yonker6277c792014-09-15 14:54:30 -0500717 Symlink_Path = Storage_Path;
Ethan Yonker66a19492015-12-10 10:19:45 -0600718 if (Mount_Point == "/data") {
719 Is_Settings_Storage = true;
720 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
721 Make_Dir("/emmc", false);
722 Symlink_Mount_Point = "/emmc";
723 } else {
724 Make_Dir("/sdcard", false);
725 Symlink_Mount_Point = "/sdcard";
726 }
727 if (Mount(false) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
728 Storage_Path = Mount_Point + "/media/0";
729 Symlink_Path = Storage_Path;
730 DataManager::SetValue(TW_INTERNAL_PATH, Mount_Point + "/media/0");
731 UnMount(true);
732 }
733 DataManager::SetValue("tw_has_internal", 1);
734 DataManager::SetValue("tw_has_data_media", 1);
735 du.add_absolute_dir(Mount_Point + "/misc/vold");
736 du.add_absolute_dir(Mount_Point + "/.layout_version");
737 du.add_absolute_dir(Mount_Point + "/system/storage.xml");
Ethan Yonker6277c792014-09-15 14:54:30 -0500738 } else {
Ethan Yonker66a19492015-12-10 10:19:45 -0600739 if (Mount(true) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
740 Storage_Path = Mount_Point + "/media/0";
741 Symlink_Path = Storage_Path;
742 UnMount(true);
743 }
Ethan Yonker6277c792014-09-15 14:54:30 -0500744 }
Ethan Yonker66a19492015-12-10 10:19:45 -0600745 du.add_absolute_dir(Mount_Point + "/media");
Ethan Yonker6277c792014-09-15 14:54:30 -0500746}
747
Dees_Troy5bf43922012-09-07 16:07:55 -0400748void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
749 char device[512], realDevice[512];
750
751 strcpy(device, Block.c_str());
752 memset(realDevice, 0, sizeof(realDevice));
753 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
754 {
755 strcpy(device, realDevice);
756 memset(realDevice, 0, sizeof(realDevice));
757 }
758
759 if (device[0] != '/') {
760 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000761 LOGERR("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400762 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000763 LOGINFO("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400764 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400765 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400766 Block = device;
767 return;
768 }
769}
770
Dees_Troy8e337f32012-10-13 22:07:49 -0400771void TWPartition::Mount_Storage_Retry(void) {
772 // On some devices, storage doesn't want to mount right away, retry and sleep
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500773 if (!Mount(true)) {
Dees_Troy8e337f32012-10-13 22:07:49 -0400774 int retry_count = 5;
775 while (retry_count > 0 && !Mount(false)) {
776 usleep(500000);
777 retry_count--;
778 }
779 Mount(true);
780 }
781}
782
Dees_Troy38bd7602012-09-14 13:33:53 -0400783bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
784 FILE *fp = NULL;
785 char line[255];
786
787 fp = fopen("/proc/mtd", "rt");
788 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000789 LOGERR("Device does not support /proc/mtd\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400790 return false;
791 }
792
793 while (fgets(line, sizeof(line), fp) != NULL)
794 {
795 char device[32], label[32];
796 unsigned long size = 0;
797 char* fstype = NULL;
798 int deviceId;
799
800 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
801
802 // Skip header and blank lines
803 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
804 continue;
805
806 // Strip off the trailing " from the label
807 label[strlen(label)-1] = '\0';
808
809 if (strcmp(label, MTD_Name.c_str()) == 0) {
810 // We found our device
811 // Strip off the trailing : from the device
812 device[strlen(device)-1] = '\0';
813 if (sscanf(device,"mtd%d", &deviceId) == 1) {
814 sprintf(device, "/dev/block/mtdblock%d", deviceId);
815 Primary_Block_Device = device;
Dees_Troy76543db2013-06-19 16:24:30 +0000816 fclose(fp);
817 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400818 }
819 }
820 }
821 fclose(fp);
822
823 return false;
824}
825
Dees_Troy51127312012-09-08 13:08:49 -0400826bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
827 struct statfs st;
828 string Local_Path = Mount_Point + "/.";
829
830 if (!Mount(Display_Error))
831 return false;
832
833 if (statfs(Local_Path.c_str(), &st) != 0) {
834 if (!Removable) {
835 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000836 LOGERR("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400837 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000838 LOGINFO("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400839 }
840 return false;
841 }
842 Size = (st.f_blocks * st.f_bsize);
843 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
844 Free = (st.f_bfree * st.f_bsize);
845 Backup_Size = Used;
846 return true;
847}
848
849bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400850 FILE* fp;
851 char command[255], line[512];
852 int include_block = 1;
853 unsigned int min_len;
854
855 if (!Mount(Display_Error))
856 return false;
857
Dees_Troy38bd7602012-09-14 13:33:53 -0400858 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -0400859 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +0200860 TWFunc::Exec_Cmd(command);
Dees_Troy51127312012-09-08 13:08:49 -0400861 fp = fopen("/tmp/dfoutput.txt", "rt");
862 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000863 LOGINFO("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400864 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400865 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400866
867 while (fgets(line, sizeof(line), fp) != NULL)
868 {
869 unsigned long blocks, used, available;
870 char device[64];
871 char tmpString[64];
872
873 if (strncmp(line, "Filesystem", 10) == 0)
874 continue;
875 if (strlen(line) < min_len) {
876 include_block = 0;
877 continue;
878 }
879 if (include_block) {
880 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
881 } else {
882 // The device block string is so long that the df information is on the next line
883 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -0400884 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400885 while (tmpString[space_count] == 32)
886 space_count++;
887 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
888 }
889
890 // Adjust block size to byte size
891 Size = blocks * 1024ULL;
892 Used = used * 1024ULL;
893 Free = available * 1024ULL;
894 Backup_Size = Used;
895 }
896 fclose(fp);
897 return true;
898}
899
Ethan Yonkerd18a8212015-12-14 10:17:00 -0600900unsigned long long TWPartition::IOCTL_Get_Block_Size() {
Ethan Yonkerd18a8212015-12-14 10:17:00 -0600901 Find_Actual_Block_Device();
Ethan Yonker483e9f42016-01-11 22:21:18 -0600902
903 return TWFunc::IOCTL_Get_Block_Size(Actual_Block_Device.c_str());
Ethan Yonkerd18a8212015-12-14 10:17:00 -0600904}
905
Dees_Troy5bf43922012-09-07 16:07:55 -0400906bool TWPartition::Find_Partition_Size(void) {
907 FILE* fp;
908 char line[512];
909 string tmpdevice;
910
igoriok87e3d932013-01-31 21:03:53 +0200911 fp = fopen("/proc/dumchar_info", "rt");
912 if (fp != NULL) {
913 while (fgets(line, sizeof(line), fp) != NULL)
914 {
915 char label[32], device[32];
916 unsigned long size = 0;
917
thatd43bf2d2014-09-21 23:13:02 +0200918 sscanf(line, "%s %lx %*x %*u %s", label, &size, device);
igoriok87e3d932013-01-31 21:03:53 +0200919
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500920 // Skip header, annotation and blank lines
igoriok87e3d932013-01-31 21:03:53 +0200921 if ((strncmp(device, "/dev/", 5) != 0) || (strlen(line) < 8))
922 continue;
923
924 tmpdevice = "/dev/";
925 tmpdevice += label;
926 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
927 Size = size;
928 fclose(fp);
929 return true;
930 }
931 }
932 }
933
Ethan Yonkerd18a8212015-12-14 10:17:00 -0600934 unsigned long long ioctl_size = IOCTL_Get_Block_Size();
935 if (ioctl_size) {
936 Size = ioctl_size;
937 return true;
938 }
939
Dees_Troy5bf43922012-09-07 16:07:55 -0400940 // In this case, we'll first get the partitions we care about (with labels)
941 fp = fopen("/proc/partitions", "rt");
942 if (fp == NULL)
943 return false;
944
945 while (fgets(line, sizeof(line), fp) != NULL)
946 {
947 unsigned long major, minor, blocks;
948 char device[512];
949 char tmpString[64];
950
Dees_Troy63c8df72012-09-10 14:02:05 -0400951 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400952 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
953
954 tmpdevice = "/dev/block/";
955 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -0400956 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400957 // Adjust block size to byte size
958 Size = blocks * 1024ULL;
959 fclose(fp);
960 return true;
961 }
962 }
963 fclose(fp);
964 return false;
965}
966
Dees_Troy5bf43922012-09-07 16:07:55 -0400967bool TWPartition::Is_Mounted(void) {
968 if (!Can_Be_Mounted)
969 return false;
970
971 struct stat st1, st2;
972 string test_path;
973
974 // Check to see if the mount point directory exists
975 test_path = Mount_Point + "/.";
976 if (stat(test_path.c_str(), &st1) != 0) return false;
977
978 // Check to see if the directory above the mount point exists
979 test_path = Mount_Point + "/../.";
980 if (stat(test_path.c_str(), &st2) != 0) return false;
981
982 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
983 int ret = (st1.st_dev != st2.st_dev) ? true : false;
984
985 return ret;
986}
987
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -0500988bool TWPartition::Is_File_System_Writable(void) {
989 if (!Is_File_System(Current_File_System) || !Is_Mounted())
990 return false;
991
992 string test_path = Mount_Point + "/.";
993 return (access(test_path.c_str(), W_OK) == 0);
994}
995
Dees_Troy5bf43922012-09-07 16:07:55 -0400996bool TWPartition::Mount(bool Display_Error) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000997 int exfat_mounted = 0;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500998 unsigned long flags = Mount_Flags;
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000999
Dees_Troy5bf43922012-09-07 16:07:55 -04001000 if (Is_Mounted()) {
1001 return true;
1002 } else if (!Can_Be_Mounted) {
1003 return false;
1004 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001005
1006 Find_Actual_Block_Device();
1007
1008 // Check the current file system before mounting
1009 Check_FS_Type();
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001010 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/exfat-fuse")) {
Dees_Troye34c1332013-02-06 19:13:00 +00001011 string cmd = "/sbin/exfat-fuse -o big_writes,max_read=131072,max_write=131072 " + Actual_Block_Device + " " + Mount_Point;
Dees_Troy2673cec2013-04-02 20:22:16 +00001012 LOGINFO("cmd: %s\n", cmd.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001013 string result;
1014 if (TWFunc::Exec_Cmd(cmd, result) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001015 LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001016 Current_File_System = "vfat";
1017 } else {
1018#ifdef TW_NO_EXFAT_FUSE
1019 UnMount(false);
1020 // We'll let the kernel handle it but using exfat-fuse to detect if the file system is actually exfat
1021 // Some kernels let us mount vfat as exfat which doesn't work out too well
1022#else
1023 exfat_mounted = 1;
1024#endif
1025 }
1026 }
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001027
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001028 if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfs-3g") || TWFunc::Path_Exists("/sbin/mount.ntfs"))) {
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001029 string cmd;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001030 string Ntfsmount_Binary = "";
1031
1032 if (TWFunc::Path_Exists("/sbin/ntfs-3g"))
1033 Ntfsmount_Binary = "ntfs-3g";
1034 else if (TWFunc::Path_Exists("/sbin/mount.ntfs"))
1035 Ntfsmount_Binary = "mount.ntfs";
1036
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001037 if (Mount_Read_Only)
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001038 cmd = "/sbin/" + Ntfsmount_Binary + " -o ro " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001039 else
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001040 cmd = "/sbin/" + Ntfsmount_Binary + " " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001041 LOGINFO("cmd: '%s'\n", cmd.c_str());
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001042
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001043 if (TWFunc::Exec_Cmd(cmd) == 0) {
1044 return true;
1045 } else {
1046 LOGINFO("ntfs-3g failed to mount, trying regular mount method.\n");
1047 }
1048 }
1049
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001050 if (Mount_Read_Only)
1051 flags |= MS_RDONLY;
1052
Dees_Troy22042032012-12-18 21:23:08 +00001053 if (Fstab_File_System == "yaffs2") {
1054 // mount an MTD partition as a YAFFS2 filesystem.
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001055 flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
1056 if (Mount_Read_Only)
1057 flags |= MS_RDONLY;
Dees_Troy76543db2013-06-19 16:24:30 +00001058 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
1059 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
1060 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001061 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001062 else
1063 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1064 return false;
1065 } else {
1066 LOGINFO("Mounted '%s' (MTD) as RO\n", Mount_Point.c_str());
1067 return true;
1068 }
1069 } else {
1070 struct stat st;
1071 string test_path = Mount_Point;
1072 if (stat(test_path.c_str(), &st) < 0) {
1073 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001074 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001075 else
1076 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1077 return false;
1078 }
1079 mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
1080 if (new_mode != st.st_mode) {
1081 LOGINFO("Fixing execute permissions for %s\n", Mount_Point.c_str());
1082 if (chmod(Mount_Point.c_str(), new_mode) < 0) {
1083 if (Display_Error)
1084 LOGERR("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1085 else
1086 LOGINFO("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1087 return false;
1088 }
1089 }
Dees_Troy22042032012-12-18 21:23:08 +00001090 return true;
Dees_Troy76543db2013-06-19 16:24:30 +00001091 }
thatc7572eb2015-03-31 18:55:30 +02001092 }
1093
1094 string mount_fs = Current_File_System;
1095 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sys/module/texfat"))
1096 mount_fs = "texfat";
1097
1098 if (!exfat_mounted &&
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001099 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, Mount_Options.c_str()) != 0 &&
1100 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, NULL) != 0) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001101#ifdef TW_NO_EXFAT_FUSE
1102 if (Current_File_System == "exfat") {
Dees_Troy2673cec2013-04-02 20:22:16 +00001103 LOGINFO("Mounting exfat failed, trying vfat...\n");
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001104 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), "vfat", 0, NULL) != 0) {
Dees_Troy85f44ed2013-01-09 18:42:36 +00001105 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001106 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy85f44ed2013-01-09 18:42:36 +00001107 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001108 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001109 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());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001110 return false;
Dees_Troy85f44ed2013-01-09 18:42:36 +00001111 }
Dees_Troyb05ddee2013-01-28 20:24:50 +00001112 } else {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001113#endif
bigbiff bigbiff26774a02014-03-29 18:22:00 -04001114 if (!Removable && Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001115 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001116 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001117 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
1118 LOGINFO("Actual block device: '%s', current file system: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001119 return false;
1120#ifdef TW_NO_EXFAT_FUSE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001121 }
1122#endif
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001123 }
Ethan Yonker253368a2014-11-25 15:00:52 -06001124
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001125 if (Removable)
1126 Update_Size(Display_Error);
1127
xiaolu9416f4f2015-06-04 08:22:23 +08001128 if (!Symlink_Mount_Point.empty() && TWFunc::Path_Exists(Symlink_Path)) {
codelover2a3d4ce2015-03-14 20:26:49 +08001129 string Command = "mount -o bind '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
Vojtech Bocek05534202013-09-11 08:11:56 +02001130 TWFunc::Exec_Cmd(Command);
Dees_Troy5bf43922012-09-07 16:07:55 -04001131 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001132 return true;
1133}
1134
1135bool TWPartition::UnMount(bool Display_Error) {
1136 if (Is_Mounted()) {
1137 int never_unmount_system;
1138
1139 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
1140 if (never_unmount_system == 1 && Mount_Point == "/system")
1141 return true; // Never unmount system if you're not supposed to unmount it
1142
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001143 if (Is_Storage)
Ethan Yonker726a0202014-12-16 20:01:38 -06001144 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001145
Dees_Troy38bd7602012-09-14 13:33:53 -04001146 if (!Symlink_Mount_Point.empty())
1147 umount(Symlink_Mount_Point.c_str());
1148
Dees_Troyb05ddee2013-01-28 20:24:50 +00001149 umount(Mount_Point.c_str());
1150 if (Is_Mounted()) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001151 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001152 gui_msg(Msg(msg::kError, "fail_unmount=Failed to unmount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy5bf43922012-09-07 16:07:55 -04001153 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001154 LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001155 return false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001156 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -04001157 return true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001158 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001159 } else {
1160 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001161 }
1162}
1163
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05001164bool TWPartition::ReMount(bool Display_Error) {
1165 if (UnMount(Display_Error))
1166 return Mount(Display_Error);
1167 return false;
1168}
1169
1170bool TWPartition::ReMount_RW(bool Display_Error) {
1171 // No need to remount if already mounted rw
1172 if (Is_File_System_Writable())
1173 return true;
1174
1175 bool ro = Mount_Read_Only;
1176 int flags = Mount_Flags;
1177
1178 Mount_Read_Only = false;
1179 Mount_Flags &= ~MS_RDONLY;
1180
1181 bool ret = ReMount(Display_Error);
1182
1183 Mount_Read_Only = ro;
1184 Mount_Flags = flags;
1185
1186 return ret;
1187}
1188
Gary Peck43acadf2012-11-21 21:19:01 -08001189bool TWPartition::Wipe(string New_File_System) {
Ethan Yonker726a0202014-12-16 20:01:38 -06001190 bool wiped = false, update_crypt = false, recreate_media = true;
Dees_Troy16c2b312013-01-15 16:51:18 +00001191 int check;
1192 string Layout_Filename = Mount_Point + "/.layout_version";
1193
Dees_Troy38bd7602012-09-14 13:33:53 -04001194 if (!Can_Be_Wiped) {
Matt Mower3c366972015-12-25 19:28:31 -06001195 gui_msg(Msg(msg::kError, "cannot_wipe=Partition {1} cannot be wiped.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001196 return false;
1197 }
1198
Dees_Troyc51f1f92012-09-20 15:32:13 -04001199 if (Mount_Point == "/cache")
Dees_Troy2673cec2013-04-02 20:22:16 +00001200 Log_Offset = 0;
Dees_Troyc51f1f92012-09-20 15:32:13 -04001201
Dees_Troy16c2b312013-01-15 16:51:18 +00001202 if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
1203 TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
1204 else
1205 unlink("/.layout_version");
Dees_Troy38bd7602012-09-14 13:33:53 -04001206
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001207 if (Has_Data_Media && Current_File_System == New_File_System) {
Dees_Troy16c2b312013-01-15 16:51:18 +00001208 wiped = Wipe_Data_Without_Wiping_Media();
Ethan Yonker5eac2222014-06-11 12:22:55 -05001209 recreate_media = false;
Dees_Troy16c2b312013-01-15 16:51:18 +00001210 } else {
Dees_Troy16c2b312013-01-15 16:51:18 +00001211 DataManager::GetValue(TW_RM_RF_VAR, check);
1212
Hashcodedabfd492013-08-29 22:45:30 -07001213 if (check || Use_Rm_Rf)
Dees_Troy16c2b312013-01-15 16:51:18 +00001214 wiped = Wipe_RMRF();
1215 else if (New_File_System == "ext4")
1216 wiped = Wipe_EXT4();
1217 else if (New_File_System == "ext2" || New_File_System == "ext3")
1218 wiped = Wipe_EXT23(New_File_System);
1219 else if (New_File_System == "vfat")
1220 wiped = Wipe_FAT();
1221 else if (New_File_System == "exfat")
1222 wiped = Wipe_EXFAT();
1223 else if (New_File_System == "yaffs2")
1224 wiped = Wipe_MTD();
Dees_Troye5017042013-08-29 16:38:55 +00001225 else if (New_File_System == "f2fs")
1226 wiped = Wipe_F2FS();
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001227 else if (New_File_System == "ntfs")
1228 wiped = Wipe_NTFS();
Dees_Troy16c2b312013-01-15 16:51:18 +00001229 else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001230 LOGERR("Unable to wipe '%s' -- unknown file system '%s'\n", Mount_Point.c_str(), New_File_System.c_str());
Dees_Troy16c2b312013-01-15 16:51:18 +00001231 unlink("/.layout_version");
1232 return false;
1233 }
1234 update_crypt = wiped;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001235 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001236
Gary Pecke8bc5d72012-12-21 06:45:25 -08001237 if (wiped) {
Dees_Troy1c1ac442013-01-17 21:42:14 +00001238 if (Mount_Point == "/cache")
1239 DataManager::Output_Version();
1240
Dees_Troy16c2b312013-01-15 16:51:18 +00001241 if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
1242 TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
1243
1244 if (update_crypt) {
1245 Setup_File_System(false);
1246 if (Is_Encrypted && !Is_Decrypted) {
1247 // just wiped an encrypted partition back to its unencrypted state
1248 Is_Encrypted = false;
1249 Is_Decrypted = false;
1250 Decrypted_Block_Device = "";
1251 if (Mount_Point == "/data") {
1252 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1253 DataManager::SetValue(TW_IS_DECRYPTED, 0);
1254 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001255 }
1256 }
Ethan Yonker5eac2222014-06-11 12:22:55 -05001257
Ethan Yonker66a19492015-12-10 10:19:45 -06001258 if (Has_Data_Media && recreate_media) {
Ethan Yonker5eac2222014-06-11 12:22:55 -05001259 Recreate_Media_Folder();
1260 }
Matt Mower209c9632016-01-20 12:08:35 -06001261 if (Is_Storage && Mount(false))
1262 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Gary Pecke8bc5d72012-12-21 06:45:25 -08001263 }
Matt Mower209c9632016-01-20 12:08:35 -06001264
Gary Pecke8bc5d72012-12-21 06:45:25 -08001265 return wiped;
Dees_Troy51a0e822012-09-05 15:24:24 -04001266}
1267
Gary Peck43acadf2012-11-21 21:19:01 -08001268bool TWPartition::Wipe() {
Gary Peck82599a82012-11-21 16:23:12 -08001269 if (Is_File_System(Current_File_System))
1270 return Wipe(Current_File_System);
1271 else
1272 return Wipe(Fstab_File_System);
Gary Peck43acadf2012-11-21 21:19:01 -08001273}
1274
Dees_Troye58d5262012-09-21 12:27:57 -04001275bool TWPartition::Wipe_AndSec(void) {
1276 if (!Has_Android_Secure)
1277 return false;
1278
Dees_Troye58d5262012-09-21 12:27:57 -04001279 if (!Mount(true))
1280 return false;
1281
Ethan Yonker74db1572015-10-28 12:44:49 -05001282 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001283 TWFunc::removeDir(Mount_Point + "/.android_secure/", true);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001284 return true;
Dees_Troye58d5262012-09-21 12:27:57 -04001285}
1286
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001287bool TWPartition::Can_Repair() {
Ethan Yonkera2719152015-05-28 09:44:41 -05001288 if (Mount_Read_Only)
1289 return false;
Matt Mower18794c82015-11-11 16:22:45 -06001290 if (Current_File_System == "vfat" && TWFunc::Path_Exists("/sbin/fsck.fat"))
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001291 return true;
1292 else if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/e2fsck"))
1293 return true;
1294 else if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/fsck.exfat"))
1295 return true;
1296 else if (Current_File_System == "f2fs" && TWFunc::Path_Exists("/sbin/fsck.f2fs"))
1297 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001298 else if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfsfix") || TWFunc::Path_Exists("/sbin/fsck.ntfs")))
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001299 return true;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001300 return false;
1301}
1302
1303bool TWPartition::Repair() {
1304 string command;
1305
1306 if (Current_File_System == "vfat") {
Matt Mower18794c82015-11-11 16:22:45 -06001307 if (!TWFunc::Path_Exists("/sbin/fsck.fat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001308 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001309 return false;
1310 }
1311 if (!UnMount(true))
1312 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001313 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001314 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06001315 command = "/sbin/fsck.fat -y " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001316 LOGINFO("Repair command: %s\n", command.c_str());
1317 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001318 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001319 return true;
1320 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001321 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001322 return false;
1323 }
1324 }
1325 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1326 if (!TWFunc::Path_Exists("/sbin/e2fsck")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001327 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001328 return false;
1329 }
1330 if (!UnMount(true))
1331 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001332 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001333 Find_Actual_Block_Device();
Ethan Yonkera2719152015-05-28 09:44:41 -05001334 command = "/sbin/e2fsck -fp " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001335 LOGINFO("Repair command: %s\n", command.c_str());
1336 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001337 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001338 return true;
1339 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001340 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001341 return false;
1342 }
1343 }
1344 if (Current_File_System == "exfat") {
1345 if (!TWFunc::Path_Exists("/sbin/fsck.exfat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001346 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001347 return false;
1348 }
1349 if (!UnMount(true))
1350 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001351 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001352 Find_Actual_Block_Device();
1353 command = "/sbin/fsck.exfat " + Actual_Block_Device;
1354 LOGINFO("Repair command: %s\n", command.c_str());
1355 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001356 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001357 return true;
1358 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001359 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001360 return false;
1361 }
1362 }
1363 if (Current_File_System == "f2fs") {
1364 if (!TWFunc::Path_Exists("/sbin/fsck.f2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001365 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001366 return false;
1367 }
1368 if (!UnMount(true))
1369 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001370 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001371 Find_Actual_Block_Device();
1372 command = "/sbin/fsck.f2fs " + Actual_Block_Device;
1373 LOGINFO("Repair command: %s\n", command.c_str());
1374 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001375 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001376 return true;
1377 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001378 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001379 return false;
1380 }
1381 }
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001382 if (Current_File_System == "ntfs") {
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001383 string Ntfsfix_Binary;
1384 if (TWFunc::Path_Exists("/sbin/ntfsfix"))
1385 Ntfsfix_Binary = "ntfsfix";
1386 else if (TWFunc::Path_Exists("/sbin/fsck.ntfs"))
1387 Ntfsfix_Binary = "fsck.ntfs";
1388 else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001389 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("ntfsfix"));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001390 return false;
1391 }
1392 if (!UnMount(true))
1393 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001394 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)(Ntfsfix_Binary));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001395 Find_Actual_Block_Device();
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001396 command = "/sbin/" + Ntfsfix_Binary + " " + Actual_Block_Device;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001397 LOGINFO("Repair command: %s\n", command.c_str());
1398 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001399 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001400 return true;
1401 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001402 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001403 return false;
1404 }
1405 }
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001406 return false;
1407}
1408
Ethan Yonkera2719152015-05-28 09:44:41 -05001409bool TWPartition::Can_Resize() {
1410 if (Mount_Read_Only)
1411 return false;
1412 if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/resize2fs"))
1413 return true;
1414 return false;
1415}
1416
1417bool TWPartition::Resize() {
1418 string command;
1419
1420 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1421 if (!Can_Repair()) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001422 LOGINFO("Cannot resize %s because %s cannot be repaired before resizing.\n", Display_Name.c_str(), Display_Name.c_str());
1423 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001424 return false;
1425 }
1426 if (!TWFunc::Path_Exists("/sbin/resize2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001427 LOGINFO("resize2fs does not exist! Cannot resize!\n");
1428 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001429 return false;
1430 }
1431 // Repair will unmount so no need to do it twice
Ethan Yonker74db1572015-10-28 12:44:49 -05001432 gui_msg(Msg("repair_resize=Repairing {1} before resizing.")( Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001433 if (!Repair())
1434 return false;
Ethan Yonker74db1572015-10-28 12:44:49 -05001435 gui_msg(Msg("resizing=Resizing {1} using {2}...")(Display_Name)("resize2fs"));
Ethan Yonkera2719152015-05-28 09:44:41 -05001436 Find_Actual_Block_Device();
1437 command = "/sbin/resize2fs " + Actual_Block_Device;
1438 if (Length != 0) {
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001439 unsigned long long Actual_Size = IOCTL_Get_Block_Size();
1440 if (Actual_Size == 0)
1441 return false;
Ethan Yonkera2719152015-05-28 09:44:41 -05001442
Ethan Yonkera2719152015-05-28 09:44:41 -05001443 unsigned long long Block_Count;
1444 if (Length < 0) {
1445 // Reduce overall size by this length
1446 Block_Count = (Actual_Size / 1024LLU) - ((unsigned long long)(Length * -1) / 1024LLU);
1447 } else {
1448 // This is the size, not a size reduction
1449 Block_Count = ((unsigned long long)(Length) / 1024LLU);
1450 }
1451 char temp[256];
1452 sprintf(temp, "%llu", Block_Count);
1453 command += " ";
1454 command += temp;
1455 command += "K";
1456 }
1457 LOGINFO("Resize command: %s\n", command.c_str());
1458 if (TWFunc::Exec_Cmd(command) == 0) {
1459 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001460 gui_msg("done=Done.");
Ethan Yonkera2719152015-05-28 09:44:41 -05001461 return true;
1462 } else {
1463 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001464 gui_msg(Msg(msg::kError, "unable_resize=Unable to resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001465 return false;
1466 }
1467 }
1468 return false;
1469}
1470
Ethan Yonker472f5062016-02-25 13:47:30 -06001471bool TWPartition::Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress) {
bigbiff7abc5fe2015-01-17 16:53:12 -05001472 if (Backup_Method == FILES) {
Ethan Yonker472f5062016-02-25 13:47:30 -06001473 return Backup_Tar(backup_folder, progress, tar_fork_pid);
bigbiff7abc5fe2015-01-17 16:53:12 -05001474 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001475 else if (Backup_Method == DD)
Ethan Yonker472f5062016-02-25 13:47:30 -06001476 return Backup_Image(backup_folder, progress);
Dees_Troy38bd7602012-09-14 13:33:53 -04001477 else if (Backup_Method == FLASH_UTILS)
Ethan Yonker472f5062016-02-25 13:47:30 -06001478 return Backup_Dump_Image(backup_folder, progress);
Dees_Troy2673cec2013-04-02 20:22:16 +00001479 LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001480 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001481}
1482
Dees_Troy43d8b002012-09-17 16:00:01 -04001483bool TWPartition::Check_MD5(string restore_folder) {
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001484 string Full_Filename, md5file;
Dees_Troy43d8b002012-09-17 16:00:01 -04001485 char split_filename[512];
1486 int index = 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001487 twrpDigest md5sum;
Dees_Troy43d8b002012-09-17 16:00:01 -04001488
Captain Throwbackff5935f2014-09-23 16:08:34 -04001489 sync();
1490
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001491 memset(split_filename, 0, sizeof(split_filename));
Dees_Troy43d8b002012-09-17 16:00:01 -04001492 Full_Filename = restore_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04001493 if (!TWFunc::Path_Exists(Full_Filename)) {
1494 // This is a split archive, we presume
1495 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
Dees_Troy2673cec2013-04-02 20:22:16 +00001496 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001497 md5file = split_filename;
1498 md5file += ".md5";
1499 if (!TWFunc::Path_Exists(md5file)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001500 gui_msg(Msg(msg::kError, "no_md5_found=No md5 file found for '{1}'. Please unselect Enable MD5 verification to restore.")(split_filename));
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001501 return false;
1502 }
1503 md5sum.setfn(split_filename);
Dees_Troy83bd4832013-05-04 12:39:56 +00001504 while (index < 1000) {
1505 if (TWFunc::Path_Exists(split_filename) && md5sum.verify_md5digest() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001506 gui_msg(Msg(msg::kError, "md5_fail_match=MD5 failed to match on '{1}'.")(split_filename));
Dees_Troy43d8b002012-09-17 16:00:01 -04001507 return false;
1508 }
1509 index++;
1510 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001511 md5sum.setfn(split_filename);
Dees_Troy43d8b002012-09-17 16:00:01 -04001512 }
Dees_Troy4a2a1262012-09-18 09:33:47 -04001513 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -04001514 } else {
1515 // Single file archive
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001516 md5file = Full_Filename + ".md5";
1517 if (!TWFunc::Path_Exists(md5file)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001518 gui_msg(Msg(msg::kError, "no_md5_found=No md5 file found for '{1}'. Please unselect Enable MD5 verification to restore.")(split_filename));
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001519 return false;
1520 }
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001521 md5sum.setfn(Full_Filename);
1522 if (md5sum.verify_md5digest() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001523 gui_msg(Msg(msg::kError, "md5_fail_match=MD5 failed to match on '{1}'.")(split_filename));
Dees_Troy43d8b002012-09-17 16:00:01 -04001524 return false;
1525 } else
1526 return true;
1527 }
1528 return false;
1529}
1530
Ethan Yonker472f5062016-02-25 13:47:30 -06001531bool TWPartition::Restore(const string& restore_folder, ProgressTracking *progress) {
Gary Peck43acadf2012-11-21 21:19:01 -08001532 string Restore_File_System;
1533
Matt Mower3c366972015-12-25 19:28:31 -06001534 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}"));
Dees_Troy2673cec2013-04-02 20:22:16 +00001535 LOGINFO("Restore filename is: %s\n", Backup_FileName.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001536
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001537 Restore_File_System = Get_Restore_File_System(restore_folder);
1538
1539 if (Is_File_System(Restore_File_System))
Ethan Yonker472f5062016-02-25 13:47:30 -06001540 return Restore_Tar(restore_folder, Restore_File_System, progress);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001541 else if (Is_Image(Restore_File_System)) {
Ethan Yonker472f5062016-02-25 13:47:30 -06001542 return Restore_Image(restore_folder, Restore_File_System, progress);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001543 }
1544
1545 LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str());
1546 return false;
1547}
1548
Ethan Yonker472f5062016-02-25 13:47:30 -06001549string TWPartition::Get_Restore_File_System(const string& restore_folder) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001550 size_t first_period, second_period;
1551 string Restore_File_System;
1552
Gary Peck43acadf2012-11-21 21:19:01 -08001553 // Parse backup filename to extract the file system before wiping
1554 first_period = Backup_FileName.find(".");
1555 if (first_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001556 LOGERR("Unable to find file system (first period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001557 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001558 }
1559 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
1560 second_period = Restore_File_System.find(".");
1561 if (second_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001562 LOGERR("Unable to find file system (second period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001563 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001564 }
1565 Restore_File_System.resize(second_period);
Dees_Troy2673cec2013-04-02 20:22:16 +00001566 LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001567 return Restore_File_System;
Dees_Troy51a0e822012-09-05 15:24:24 -04001568}
1569
1570string TWPartition::Backup_Method_By_Name() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001571 if (Backup_Method == NONE)
1572 return "none";
1573 else if (Backup_Method == FILES)
1574 return "files";
1575 else if (Backup_Method == DD)
1576 return "dd";
1577 else if (Backup_Method == FLASH_UTILS)
1578 return "flash_utils";
1579 else
1580 return "undefined";
1581 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -04001582}
1583
1584bool TWPartition::Decrypt(string Password) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001585 LOGINFO("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001586 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -04001587 return 1;
1588}
1589
1590bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001591 bool Save_Data_Media = Has_Data_Media;
1592
1593 if (!UnMount(true))
1594 return false;
1595
Dees_Troy38bd7602012-09-14 13:33:53 -04001596 Has_Data_Media = false;
Dees_Troy74fb2e92013-04-15 14:35:47 +00001597 Decrypted_Block_Device = "";
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001598#ifdef TW_INCLUDE_CRYPTO
1599 if (Is_Decrypted) {
1600 if (!UnMount(true))
1601 return false;
Matt Mower2b18a532015-02-20 16:58:05 -06001602 if (delete_crypto_blk_dev((char*)("userdata")) != 0) {
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001603 LOGERR("Error deleting crypto block device, continuing anyway.\n");
1604 }
1605 }
1606#endif
Dees_Troy74fb2e92013-04-15 14:35:47 +00001607 Is_Decrypted = false;
1608 Is_Encrypted = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001609 Find_Actual_Block_Device();
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001610 if (Crypto_Key_Location == "footer") {
1611 int newlen, fd;
1612 if (Length != 0) {
1613 newlen = Length;
1614 if (newlen < 0)
1615 newlen = newlen * -1;
1616 } else {
1617 newlen = CRYPT_FOOTER_OFFSET;
1618 }
1619 if ((fd = open(Actual_Block_Device.c_str(), O_RDWR)) < 0) {
1620 gui_print_color("warning", "Unable to open '%s' to wipe crypto key\n", Actual_Block_Device.c_str());
1621 } else {
1622 unsigned int block_count;
1623 if ((ioctl(fd, BLKGETSIZE, &block_count)) == -1) {
1624 gui_print_color("warning", "Unable to get block size for wiping crypto footer.\n");
1625 } else {
1626 off64_t offset = ((off64_t)block_count * 512) - newlen;
1627 if (lseek64(fd, offset, SEEK_SET) == -1) {
1628 gui_print_color("warning", "Unable to lseek64 for wiping crypto footer.\n");
1629 } else {
1630 void* buffer = malloc(newlen);
1631 if (!buffer) {
1632 gui_print_color("warning", "Failed to malloc for wiping crypto footer.\n");
1633 } else {
1634 memset(buffer, 0, newlen);
1635 int ret = write(fd, buffer, newlen);
1636 if (ret != newlen) {
1637 gui_print_color("warning", "Failed to wipe crypto footer.\n");
1638 } else {
1639 LOGINFO("Successfully wiped crypto footer.\n");
1640 }
Matt Mower13a8f0b2015-09-26 15:40:03 -05001641 free(buffer);
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001642 }
1643 }
1644 }
1645 close(fd);
1646 }
1647 } else {
Ethan Yonkerc2dafbb2016-03-15 22:20:59 -05001648 if (TWFunc::IOCTL_Get_Block_Size(Crypto_Key_Location.c_str()) >= 16384LLU) {
1649 string Command = "dd of='" + Crypto_Key_Location + "' if=/dev/zero bs=16384 count=1";
1650 TWFunc::Exec_Cmd(Command);
1651 } else {
1652 LOGINFO("Crypto key location reports size < 16K so not wiping crypto footer.\n");
1653 }
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001654 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001655 if (Wipe(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001656 Has_Data_Media = Save_Data_Media;
1657 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
1658 Recreate_Media_Folder();
Ethan Yonker726a0202014-12-16 20:01:38 -06001659 if (Mount(false))
1660 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001661 }
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001662 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
Ethan Yonker83e82572014-04-04 10:59:28 -05001663#ifndef TW_OEM_BUILD
Ethan Yonker74db1572015-10-28 12:44:49 -05001664 gui_msg("format_data_msg=You may need to reboot recovery to be able to use /data again.");
Ethan Yonker83e82572014-04-04 10:59:28 -05001665#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001666 return true;
1667 } else {
1668 Has_Data_Media = Save_Data_Media;
Ethan Yonker74db1572015-10-28 12:44:49 -05001669 gui_err("format_data_err=Unable to format to remove encryption.");
Ethan Yonker726a0202014-12-16 20:01:38 -06001670 if (Has_Data_Media && Mount(false))
1671 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001672 return false;
1673 }
1674 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001675}
1676
1677void TWPartition::Check_FS_Type() {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001678 const char* type;
1679 blkid_probe pr;
Dees_Troy5bf43922012-09-07 16:07:55 -04001680
Dees_Troy68cab492012-12-12 19:29:35 +00001681 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd" || Fstab_File_System == "bml" || Ignore_Blkid)
1682 return; // Running blkid on some mtd devices causes a massive crash or needs to be skipped
Dees_Troy5bf43922012-09-07 16:07:55 -04001683
Dees_Troy38bd7602012-09-14 13:33:53 -04001684 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -04001685 if (!Is_Present)
1686 return;
Dees_Troy51127312012-09-08 13:08:49 -04001687
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001688 pr = blkid_new_probe_from_filename(Actual_Block_Device.c_str());
1689 if (blkid_do_fullprobe(pr)) {
1690 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001691 LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001692 return;
Dees_Troy5bf43922012-09-07 16:07:55 -04001693 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001694
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001695 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001696 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001697 LOGINFO("can't find filesystem on device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001698 return;
1699 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001700
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001701 Current_File_System = type;
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001702 blkid_free_probe(pr);
Dees_Troy51a0e822012-09-05 15:24:24 -04001703}
1704
Gary Peck43acadf2012-11-21 21:19:01 -08001705bool TWPartition::Wipe_EXT23(string File_System) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001706 if (!UnMount(true))
1707 return false;
1708
Dees_Troy43d8b002012-09-17 16:00:01 -04001709 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001710 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001711
Greg Wallace4b44fef2015-12-29 15:33:24 -05001712 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mke2fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001713 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001714 command = "mke2fs -t " + File_System + " -m 0 " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001715 LOGINFO("mke2fs command: %s\n", command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001716 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001717 Current_File_System = File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04001718 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001719 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001720 return true;
1721 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001722 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001723 return false;
1724 }
1725 } else
1726 return Wipe_RMRF();
1727
1728 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001729}
1730
1731bool TWPartition::Wipe_EXT4() {
Ethan Yonker25f20c12014-10-14 09:04:43 -05001732 Find_Actual_Block_Device();
1733 if (!Is_Present) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001734 LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
1735 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Ethan Yonker25f20c12014-10-14 09:04:43 -05001736 return false;
1737 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001738 if (!UnMount(true))
1739 return false;
1740
Dees_Troyb3265ab2013-08-30 02:59:14 +00001741#if defined(HAVE_SELINUX) && defined(USE_EXT4)
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001742 int ret;
1743 char *secontext = NULL;
1744
Greg Wallace4b44fef2015-12-29 15:33:24 -05001745 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001746
Dees Troy99c8dbf2014-03-10 16:53:58 +00001747 if (!selinux_handle || selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001748 LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
1749 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
1750 } else {
1751 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
1752 }
1753 if (ret != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001754 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troya95f55c2013-08-17 13:14:43 +00001755 return false;
1756 } else {
bigbiff bigbiffc49d7062013-10-11 20:28:00 -04001757 string sedir = Mount_Point + "/lost+found";
1758 PartitionManager.Mount_By_Path(sedir.c_str(), true);
1759 rmdir(sedir.c_str());
1760 mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
Dees_Troya95f55c2013-08-17 13:14:43 +00001761 return true;
1762 }
1763#else
Dees_Troy43d8b002012-09-17 16:00:01 -04001764 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001765 string Command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001766
Greg Wallace4b44fef2015-12-29 15:33:24 -05001767 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001768 Find_Actual_Block_Device();
1769 Command = "make_ext4fs";
1770 if (!Is_Decrypted && Length != 0) {
1771 // Only use length if we're not decrypted
1772 char len[32];
1773 sprintf(len, "%i", Length);
1774 Command += " -l ";
1775 Command += len;
1776 }
Dees_Troy5295d582013-09-06 15:51:08 +00001777 if (TWFunc::Path_Exists("/file_contexts")) {
1778 Command += " -S /file_contexts";
1779 }
1780 Command += " -a " + Mount_Point + " " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001781 LOGINFO("make_ext4fs command: %s\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001782 if (TWFunc::Exec_Cmd(Command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001783 Current_File_System = "ext4";
Dees_Troye58d5262012-09-21 12:27:57 -04001784 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001785 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001786 return true;
1787 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001788 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001789 return false;
1790 }
1791 } else
Gary Peck43acadf2012-11-21 21:19:01 -08001792 return Wipe_EXT23("ext4");
Dees_Troya95f55c2013-08-17 13:14:43 +00001793#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001794 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001795}
1796
1797bool TWPartition::Wipe_FAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001798 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001799
Matt Mower18794c82015-11-11 16:22:45 -06001800 if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001801 if (!UnMount(true))
1802 return false;
1803
Greg Wallace4b44fef2015-12-29 15:33:24 -05001804 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001805 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06001806 command = "mkfs.fat " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001807 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001808 Current_File_System = "vfat";
Dees_Troye58d5262012-09-21 12:27:57 -04001809 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001810 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001811 return true;
1812 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001813 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001814 return false;
1815 }
1816 return true;
1817 }
1818 else
1819 return Wipe_RMRF();
1820
1821 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001822}
1823
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001824bool TWPartition::Wipe_EXFAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001825 string command;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001826
1827 if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
1828 if (!UnMount(true))
1829 return false;
1830
Greg Wallace4b44fef2015-12-29 15:33:24 -05001831 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkexfatfs"));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001832 Find_Actual_Block_Device();
1833 command = "mkexfatfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001834 if (TWFunc::Exec_Cmd(command) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001835 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001836 gui_msg("done=Done.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001837 return true;
1838 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001839 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001840 return false;
1841 }
1842 return true;
1843 }
1844 return false;
1845}
1846
Dees_Troy38bd7602012-09-14 13:33:53 -04001847bool TWPartition::Wipe_MTD() {
1848 if (!UnMount(true))
1849 return false;
1850
Greg Wallace4b44fef2015-12-29 15:33:24 -05001851 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("MTD"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001852
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001853 mtd_scan_partitions();
1854 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
1855 if (mtd == NULL) {
1856 LOGERR("No mtd partition named '%s'", MTD_Name.c_str());
1857 return false;
1858 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001859
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001860 MtdWriteContext* ctx = mtd_write_partition(mtd);
1861 if (ctx == NULL) {
1862 LOGERR("Can't write '%s', failed to format.", MTD_Name.c_str());
1863 return false;
1864 }
1865 if (mtd_erase_blocks(ctx, -1) == -1) {
1866 mtd_write_close(ctx);
1867 LOGERR("Failed to format '%s'", MTD_Name.c_str());
1868 return false;
1869 }
1870 if (mtd_write_close(ctx) != 0) {
1871 LOGERR("Failed to close '%s'", MTD_Name.c_str());
1872 return false;
1873 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001874 Current_File_System = "yaffs2";
Dees_Troye58d5262012-09-21 12:27:57 -04001875 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001876 gui_msg("done=Done.");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001877 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001878}
1879
1880bool TWPartition::Wipe_RMRF() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001881 if (!Mount(true))
1882 return false;
Ethan Yonker726a0202014-12-16 20:01:38 -06001883 // This is the only wipe that leaves the partition mounted, so we
1884 // must manually remove the partition from MTP if it is a storage
1885 // partition.
1886 if (Is_Storage)
1887 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001888
Ethan Yonker74db1572015-10-28 12:44:49 -05001889 gui_msg(Msg("remove_all=Removing all files under '{1}'")(Mount_Point));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001890 TWFunc::removeDir(Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04001891 Recreate_AndSec_Folder();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001892 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001893}
1894
Dees_Troye5017042013-08-29 16:38:55 +00001895bool TWPartition::Wipe_F2FS() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001896 string command;
Dees_Troye5017042013-08-29 16:38:55 +00001897
1898 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
1899 if (!UnMount(true))
1900 return false;
1901
Greg Wallace4b44fef2015-12-29 15:33:24 -05001902 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.f2fs"));
Dees_Troye5017042013-08-29 16:38:55 +00001903 Find_Actual_Block_Device();
Greg Wallace558aef72016-01-19 21:14:30 -05001904 command = "mkfs.f2fs -t 0";
dhacker29a3fa75f2015-01-17 19:42:33 -05001905 if (!Is_Decrypted && Length != 0) {
1906 // Only use length if we're not decrypted
1907 char len[32];
1908 int mod_length = Length;
1909 if (Length < 0)
1910 mod_length *= -1;
1911 sprintf(len, "%i", mod_length);
1912 command += " -r ";
1913 command += len;
1914 }
1915 command += " " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001916 if (TWFunc::Exec_Cmd(command) == 0) {
Dees_Troye5017042013-08-29 16:38:55 +00001917 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001918 gui_msg("done=Done.");
Dees_Troye5017042013-08-29 16:38:55 +00001919 return true;
1920 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001921 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troye5017042013-08-29 16:38:55 +00001922 return false;
1923 }
1924 return true;
1925 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001926 LOGINFO("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
Dees_Troye5017042013-08-29 16:38:55 +00001927 return Wipe_RMRF();
1928 }
1929 return false;
1930}
1931
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001932bool TWPartition::Wipe_NTFS() {
1933 string command;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001934 string Ntfsmake_Binary;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001935
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001936 if (TWFunc::Path_Exists("/sbin/mkntfs"))
1937 Ntfsmake_Binary = "mkntfs";
1938 else if (TWFunc::Path_Exists("/sbin/mkfs.ntfs"))
1939 Ntfsmake_Binary = "mkfs.ntfs";
1940 else
1941 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001942
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001943 if (!UnMount(true))
1944 return false;
1945
Greg Wallace4b44fef2015-12-29 15:33:24 -05001946 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)(Ntfsmake_Binary));
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001947 Find_Actual_Block_Device();
1948 command = "/sbin/" + Ntfsmake_Binary + " " + Actual_Block_Device;
1949 if (TWFunc::Exec_Cmd(command) == 0) {
1950 Recreate_AndSec_Folder();
1951 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001952 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001953 } else {
1954 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
1955 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001956 }
1957 return false;
1958}
1959
Dees_Troy51a0e822012-09-05 15:24:24 -04001960bool TWPartition::Wipe_Data_Without_Wiping_Media() {
Ethan Yonker83e82572014-04-04 10:59:28 -05001961#ifdef TW_OEM_BUILD
1962 // In an OEM Build we want to do a full format
1963 return Wipe_Encryption();
1964#else
Ethan Yonker66a19492015-12-10 10:19:45 -06001965 bool ret = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04001966
Dees_Troy38bd7602012-09-14 13:33:53 -04001967 if (!Mount(true))
1968 return false;
1969
Ethan Yonker74db1572015-10-28 12:44:49 -05001970 gui_msg("wiping_data=Wiping data without wiping /data/media ...");
Ethan Yonker66a19492015-12-10 10:19:45 -06001971 ret = Wipe_Data_Without_Wiping_Media_Func(Mount_Point + "/");
1972 if (ret)
1973 gui_msg("done=Done.");
1974 return ret;
1975#endif // ifdef TW_OEM_BUILD
1976}
1977
1978bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unused) {
1979 string dir;
Dees_Troy38bd7602012-09-14 13:33:53 -04001980
1981 DIR* d;
Ethan Yonker66a19492015-12-10 10:19:45 -06001982 d = opendir(parent.c_str());
Dees_Troy16b74352012-11-14 22:27:31 +00001983 if (d != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001984 struct dirent* de;
1985 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001986 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001987
Ethan Yonker66a19492015-12-10 10:19:45 -06001988 dir = parent;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001989 dir.append(de->d_name);
Ethan Yonker66a19492015-12-10 10:19:45 -06001990 if (du.check_skip_dirs(dir)) {
1991 LOGINFO("skipped '%s'\n", dir.c_str());
1992 continue;
1993 }
Dees_Troyce675462013-01-09 19:48:21 +00001994 if (de->d_type == DT_DIR) {
Ethan Yonker66a19492015-12-10 10:19:45 -06001995 dir.append("/");
1996 if (!Wipe_Data_Without_Wiping_Media_Func(dir)) {
1997 closedir(d);
1998 return false;
1999 }
2000 rmdir(dir.c_str());
bigbiff bigbiff98f1f902013-01-19 18:46:13 -05002001 } else if (de->d_type == DT_REG || de->d_type == DT_LNK || de->d_type == DT_FIFO || de->d_type == DT_SOCK) {
Dees_Troyce675462013-01-09 19:48:21 +00002002 if (!unlink(dir.c_str()))
Dees_Troy2673cec2013-04-02 20:22:16 +00002003 LOGINFO("Unable to unlink '%s'\n", dir.c_str());
Dees_Troyce675462013-01-09 19:48:21 +00002004 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002005 }
2006 closedir(d);
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05002007
Dees_Troy16b74352012-11-14 22:27:31 +00002008 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04002009 }
Ethan Yonker74db1572015-10-28 12:44:49 -05002010 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy16b74352012-11-14 22:27:31 +00002011 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002012}
2013
Ethan Yonker472f5062016-02-25 13:47:30 -06002014bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *progress, pid_t &tar_fork_pid) {
2015 string Full_FileName;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002016 twrpTar tar;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05002017
Dees_Troy43d8b002012-09-17 16:00:01 -04002018 if (!Mount(true))
2019 return false;
2020
Dees_Troya13d74f2013-03-24 08:54:55 -05002021 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up");
Ethan Yonker74db1572015-10-28 12:44:49 -05002022 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002023
Ethan Yonker472f5062016-02-25 13:47:30 -06002024 DataManager::GetValue(TW_USE_COMPRESSION_VAR, tar.use_compression);
Matt Mowerbb81e5d2014-03-20 18:05:41 -05002025
Dees_Troy83bd4832013-05-04 12:39:56 +00002026#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
Ethan Yonker472f5062016-02-25 13:47:30 -06002027 if (Can_Encrypt_Backup) {
2028 DataManager::GetValue("tw_encrypt_backup", tar.use_encryption);
2029 if (tar.use_encryption) {
2030 if (Use_Userdata_Encryption)
2031 tar.userdata_encryption = tar.use_encryption;
2032 string Password;
2033 DataManager::GetValue("tw_backup_password", Password);
2034 tar.setpassword(Password);
2035 } else {
2036 tar.use_encryption = 0;
2037 }
Dees_Troy83bd4832013-05-04 12:39:56 +00002038 }
2039#endif
Dees_Troy43d8b002012-09-17 16:00:01 -04002040
Ethan Yonker472f5062016-02-25 13:47:30 -06002041 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002042 Full_FileName = backup_folder + "/" + Backup_FileName;
Dees_Troy83bd4832013-05-04 12:39:56 +00002043 tar.has_data_media = Has_Data_Media;
Dees Troye0a433a2013-12-02 04:10:37 +00002044 Full_FileName = backup_folder + "/" + Backup_FileName;
2045 tar.setdir(Backup_Path);
2046 tar.setfn(Full_FileName);
2047 tar.setsize(Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002048 tar.partition_name = Backup_Name;
2049 tar.backup_folder = backup_folder;
Ethan Yonker472f5062016-02-25 13:47:30 -06002050 if (tar.createTarFork(progress, tar_fork_pid) != 0)
Dees Troye0a433a2013-12-02 04:10:37 +00002051 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04002052 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002053}
2054
Ethan Yonker472f5062016-02-25 13:47:30 -06002055bool TWPartition::Backup_Image(const string& backup_folder, ProgressTracking *progress) {
2056 string Full_FileName;
igoriok87e3d932013-01-31 21:03:53 +02002057
Ethan Yonker74db1572015-10-28 12:44:49 -05002058 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2059 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002060
Ethan Yonker472f5062016-02-25 13:47:30 -06002061 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Dees_Troy43d8b002012-09-17 16:00:01 -04002062 Full_FileName = backup_folder + "/" + Backup_FileName;
2063
Ethan Yonker472f5062016-02-25 13:47:30 -06002064 if (!Raw_Read_Write(Actual_Block_Device, Full_FileName, Backup_Size, progress))
2065 return false;
2066
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06002067 tw_set_default_metadata(Full_FileName.c_str());
Dees_Troyc154ac22012-10-12 15:36:47 -04002068 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002069 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName));
Dees_Troy7c2dec82012-09-26 09:49:14 -04002070 return false;
2071 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002072 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002073}
2074
Ethan Yonker472f5062016-02-25 13:47:30 -06002075bool TWPartition::Raw_Read_Write(const string& input_file, const string& output_file, const unsigned long long input_size, ProgressTracking *progress) {
2076 unsigned long long RW_Block_Size, Remain;
2077 int src_fd = -1, dest_fd = -1, bs;
2078 bool ret = false;
2079 void* buffer = NULL;
2080 unsigned long long backedup_size = 0;
2081
2082 RW_Block_Size = 1048576LLU; // 1MB
2083 Remain = input_size;
2084
2085 src_fd = open(input_file.c_str(), O_RDONLY | O_LARGEFILE);
2086 if (src_fd < 0) {
2087 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(input_file)(strerror(errno)));
2088 return false;
2089 }
2090 dest_fd = open(output_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR);
2091 if (dest_fd < 0) {
2092 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(output_file)(strerror(errno)));
2093 goto exit;
2094 }
2095 bs = (int)(RW_Block_Size);
2096 buffer = malloc((size_t)bs);
2097 if (!buffer) {
2098 LOGINFO("Raw_Read_Write failed to malloc\n");
2099 goto exit;
2100 }
2101 LOGINFO("Reading '%s', writing '%s'\n", input_file.c_str(), output_file.c_str());
2102 if (progress)
2103 progress->SetPartitionSize(input_size);
2104 while (Remain > 0) {
2105 if (Remain < RW_Block_Size)
2106 bs = (int)(Remain);
2107 if (read(src_fd, buffer, bs) != bs) {
2108 LOGINFO("Error reading source fd (%s)\n", strerror(errno));
2109 goto exit;
2110 }
2111 if (write(dest_fd, buffer, bs) != bs) {
2112 LOGINFO("Error writing destination fd (%s)\n", strerror(errno));
2113 goto exit;
2114 }
2115 backedup_size += (unsigned long long)(bs);
2116 Remain -= (unsigned long long)(bs);
2117 if (progress)
2118 progress->UpdateSize(backedup_size);
2119 if (PartitionManager.Check_Backup_Cancel() != 0)
2120 goto exit;
2121 }
2122 if (progress)
2123 progress->UpdateDisplayDetails(true);
2124 fsync(dest_fd);
2125 ret = true;
2126exit:
2127 if (src_fd >= 0)
2128 close(src_fd);
2129 if (dest_fd >= 0)
2130 close(dest_fd);
2131 if (buffer)
2132 free(buffer);
2133 return ret;
2134}
2135
2136bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTracking *progress) {
Vojtech Bocek05534202013-09-11 08:11:56 +02002137 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04002138
Ethan Yonker74db1572015-10-28 12:44:49 -05002139 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2140 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002141
Ethan Yonker472f5062016-02-25 13:47:30 -06002142 if (progress)
2143 progress->SetPartitionSize(Backup_Size);
Dees_Troy43d8b002012-09-17 16:00:01 -04002144
Ethan Yonker472f5062016-02-25 13:47:30 -06002145 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Dees_Troy43d8b002012-09-17 16:00:01 -04002146 Full_FileName = backup_folder + "/" + Backup_FileName;
2147
2148 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
Dees_Troy2673cec2013-04-02 20:22:16 +00002149 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02002150 TWFunc::Exec_Cmd(Command);
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06002151 tw_set_default_metadata(Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04002152 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
2153 // Actual size may not match backup size due to bad blocks on MTD devices so just check for 0 bytes
Matt Mower3c366972015-12-25 19:28:31 -06002154 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName));
Dees_Troy7c2dec82012-09-26 09:49:14 -04002155 return false;
2156 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002157 if (progress)
2158 progress->UpdateSize(Backup_Size);
Dees_Troy43d8b002012-09-17 16:00:01 -04002159 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002160}
2161
Ethan Yonker472f5062016-02-25 13:47:30 -06002162unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002163 InfoManager restore_info(restore_folder + "/" + Backup_Name + ".info");
2164 if (restore_info.LoadValues() == 0) {
2165 if (restore_info.GetValue("backup_size", Restore_Size) == 0) {
2166 LOGINFO("Read info file, restore size is %llu\n", Restore_Size);
2167 return Restore_Size;
2168 }
2169 }
2170 string Full_FileName, Restore_File_System = Get_Restore_File_System(restore_folder);
2171
2172 Full_FileName = restore_folder + "/" + Backup_FileName;
2173
2174 if (Is_Image(Restore_File_System)) {
2175 Restore_Size = TWFunc::Get_File_Size(Full_FileName);
2176 return Restore_Size;
2177 }
2178
2179 twrpTar tar;
2180 tar.setdir(Backup_Path);
2181 tar.setfn(Full_FileName);
2182 tar.backup_name = Backup_Name;
2183#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2184 string Password;
2185 DataManager::GetValue("tw_restore_password", Password);
2186 if (!Password.empty())
2187 tar.setpassword(Password);
2188#endif
2189 tar.partition_name = Backup_Name;
2190 tar.backup_folder = restore_folder;
2191 Restore_Size = tar.get_size();
2192 return Restore_Size;
2193}
2194
Ethan Yonker472f5062016-02-25 13:47:30 -06002195bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) {
2196 string Full_FileName;
Dees Troy4159aed2014-02-28 17:24:43 +00002197 bool ret = false;
Dees_Troy43d8b002012-09-17 16:00:01 -04002198
Dees_Troye58d5262012-09-21 12:27:57 -04002199 if (Has_Android_Secure) {
Dees_Troye58d5262012-09-21 12:27:57 -04002200 if (!Wipe_AndSec())
2201 return false;
Gary Peck43acadf2012-11-21 21:19:01 -08002202 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002203 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
Ethan Yonker5eac2222014-06-11 12:22:55 -05002204 if (Has_Data_Media && Mount_Point == "/data" && Restore_File_System != Current_File_System) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002205 gui_msg(Msg(msg::kWarning, "datamedia_fs_restore=WARNING: This /data backup was made with {1} file system! The backup may not boot unless you change back to {1}.")(Restore_File_System));
Ethan Yonker5eac2222014-06-11 12:22:55 -05002206 if (!Wipe_Data_Without_Wiping_Media())
2207 return false;
2208 } else {
2209 if (!Wipe(Restore_File_System))
2210 return false;
2211 }
Dees_Troye58d5262012-09-21 12:27:57 -04002212 }
Matt Mower3c366972015-12-25 19:28:31 -06002213 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002214 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002215
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002216 // Remount as read/write as needed so we can restore the backup
2217 if (!ReMount_RW(true))
Dees_Troy43d8b002012-09-17 16:00:01 -04002218 return false;
2219
Dees_Troy4a2a1262012-09-18 09:33:47 -04002220 Full_FileName = restore_folder + "/" + Backup_FileName;
Ethan Yonker87af5632014-02-10 11:56:35 -06002221 twrpTar tar;
2222 tar.setdir(Backup_Path);
2223 tar.setfn(Full_FileName);
2224 tar.backup_name = Backup_Name;
2225#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2226 string Password;
2227 DataManager::GetValue("tw_restore_password", Password);
2228 if (!Password.empty())
2229 tar.setpassword(Password);
2230#endif
Ethan Yonker472f5062016-02-25 13:47:30 -06002231 progress->SetPartitionSize(Get_Restore_Size(restore_folder));
2232 if (tar.extractTarFork(progress) != 0)
Dees Troy4159aed2014-02-28 17:24:43 +00002233 ret = false;
2234 else
2235 ret = true;
2236#ifdef HAVE_CAPABILITIES
2237 // Restore capabilities to the run-as binary
2238 if (Mount_Point == "/system" && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
2239 struct vfs_cap_data cap_data;
2240 uint64_t capabilities = (1 << CAP_SETUID) | (1 << CAP_SETGID);
2241
2242 memset(&cap_data, 0, sizeof(cap_data));
2243 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
2244 cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
2245 cap_data.data[0].inheritable = 0;
2246 cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
2247 cap_data.data[1].inheritable = 0;
2248 if (setxattr("/system/bin/run-as", XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
2249 LOGINFO("Failed to reset capabilities of /system/bin/run-as binary.\n");
2250 } else {
2251 LOGINFO("Reset capabilities of /system/bin/run-as binary successful.\n");
2252 }
2253 }
2254#endif
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002255 if (Mount_Read_Only || Mount_Flags & MS_RDONLY)
2256 // Remount as read only when restoration is complete
2257 ReMount(true);
2258
Dees Troy4159aed2014-02-28 17:24:43 +00002259 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04002260}
2261
Ethan Yonker472f5062016-02-25 13:47:30 -06002262bool TWPartition::Restore_Image(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002263 string Full_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04002264
Matt Mower3c366972015-12-25 19:28:31 -06002265 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002266 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002267 Full_FileName = restore_folder + "/" + Backup_FileName;
Gary Peck15e623d2012-11-21 21:07:58 -08002268
Ethan Yonker96af84a2015-01-05 14:58:36 -06002269 if (Restore_File_System == "emmc") {
Ethan Yonker472f5062016-02-25 13:47:30 -06002270 unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Full_FileName));
2271 if (!Raw_Read_Write(Full_FileName, Actual_Block_Device, file_size, progress))
Ethan Yonker96af84a2015-01-05 14:58:36 -06002272 return false;
2273 } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") {
Ethan Yonker472f5062016-02-25 13:47:30 -06002274 if (!Flash_Image_FI(Full_FileName, progress))
Ethan Yonker96af84a2015-01-05 14:58:36 -06002275 return false;
Gary Peck15e623d2012-11-21 21:07:58 -08002276 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002277 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002278}
Dees_Troy5bf43922012-09-07 16:07:55 -04002279
2280bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy0550cfb2012-10-13 11:56:13 -04002281 bool ret = false, Was_Already_Mounted = false;
Dees_Troy51127312012-09-08 13:08:49 -04002282
Dees_Troyab10ee22012-09-21 14:27:30 -04002283 if (!Can_Be_Mounted && !Is_Encrypted)
Dees_Troy5bf43922012-09-07 16:07:55 -04002284 return false;
2285
Dees_Troy0550cfb2012-10-13 11:56:13 -04002286 Was_Already_Mounted = Is_Mounted();
Dees_Troy38bd7602012-09-14 13:33:53 -04002287 if (Removable || Is_Encrypted) {
2288 if (!Mount(false))
2289 return true;
2290 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04002291 return false;
Dees_Troy51127312012-09-08 13:08:49 -04002292
2293 ret = Get_Size_Via_statfs(Display_Error);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002294 if (!ret || Size == 0) {
2295 if (!Get_Size_Via_df(Display_Error)) {
2296 if (!Was_Already_Mounted)
2297 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -04002298 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002299 }
2300 }
Dees_Troy51127312012-09-08 13:08:49 -04002301
Dees_Troy5bf43922012-09-07 16:07:55 -04002302 if (Has_Data_Media) {
2303 if (Mount(Display_Error)) {
Dees_Troy51127312012-09-08 13:08:49 -04002304 unsigned long long data_media_used, actual_data;
Ethan Yonker66a19492015-12-10 10:19:45 -06002305 Used = du.Get_Folder_Size(Mount_Point);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002306 Backup_Size = Used;
2307 int bak = (int)(Used / 1048576LLU);
Dees_Troy51127312012-09-08 13:08:49 -04002308 int fre = (int)(Free / 1048576LLU);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002309 LOGINFO("Data backup size is %iMB, free: %iMB.\n", bak, fre);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002310 } else {
2311 if (!Was_Already_Mounted)
2312 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002313 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002314 }
Dees_Troye58d5262012-09-21 12:27:57 -04002315 } else if (Has_Android_Secure) {
2316 if (Mount(Display_Error))
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002317 Backup_Size = du.Get_Folder_Size(Backup_Path);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002318 else {
2319 if (!Was_Already_Mounted)
2320 UnMount(false);
Dees_Troye58d5262012-09-21 12:27:57 -04002321 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002322 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002323 }
Dees_Troy0550cfb2012-10-13 11:56:13 -04002324 if (!Was_Already_Mounted)
2325 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002326 return true;
Dees_Troy51127312012-09-08 13:08:49 -04002327}
Dees_Troy38bd7602012-09-14 13:33:53 -04002328
2329void TWPartition::Find_Actual_Block_Device(void) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04002330 if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002331 Actual_Block_Device = Decrypted_Block_Device;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04002332 if (TWFunc::Path_Exists(Decrypted_Block_Device))
Dees_Troy38bd7602012-09-14 13:33:53 -04002333 Is_Present = true;
Dees_Troy43d8b002012-09-17 16:00:01 -04002334 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002335 Is_Present = true;
2336 Actual_Block_Device = Primary_Block_Device;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002337 return;
2338 }
2339 if (Is_Decrypted) {
Dees_Troy43d8b002012-09-17 16:00:01 -04002340 } else if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy3f04d032012-10-07 18:20:09 -04002341 Actual_Block_Device = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -04002342 Is_Present = true;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002343 } else {
Dees_Troy38bd7602012-09-14 13:33:53 -04002344 Is_Present = false;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002345 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002346}
2347
2348void TWPartition::Recreate_Media_Folder(void) {
2349 string Command;
Ethan Yonker66a19492015-12-10 10:19:45 -06002350 string Media_Path = Mount_Point + "/media";
Dees_Troy38bd7602012-09-14 13:33:53 -04002351
2352 if (!Mount(true)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002353 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Media_Path));
2354 } else if (!TWFunc::Path_Exists(Media_Path)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002355 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker66a19492015-12-10 10:19:45 -06002356 LOGINFO("Recreating %s folder.\n", Media_Path.c_str());
2357 mkdir(Media_Path.c_str(), 0770);
xiaolu9416f4f2015-06-04 08:22:23 +08002358 string Internal_path = DataManager::GetStrValue("tw_internal_path");
2359 if (!Internal_path.empty()) {
2360 LOGINFO("Recreating %s folder.\n", Internal_path.c_str());
2361 mkdir(Internal_path.c_str(), 0770);
2362 }
2363#ifdef TW_INTERNAL_STORAGE_PATH
2364 mkdir(EXPAND(TW_INTERNAL_STORAGE_PATH), 0770);
2365#endif
Ethan Yonker5ef301e2014-10-14 10:04:44 -05002366#ifdef HAVE_SELINUX
thata3d31fb2014-12-21 22:27:40 +01002367 // Afterwards, we will try to set the
2368 // default metadata that we were hopefully able to get during
2369 // early boot.
Ethan Yonker66a19492015-12-10 10:19:45 -06002370 tw_set_default_metadata(Media_Path.c_str());
xiaolu9416f4f2015-06-04 08:22:23 +08002371 if (!Internal_path.empty())
2372 tw_set_default_metadata(Internal_path.c_str());
Ethan Yonker5ef301e2014-10-14 10:04:44 -05002373#endif
Ethan Yonker5eac2222014-06-11 12:22:55 -05002374 // Toggle mount to ensure that "internal sdcard" gets mounted
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002375 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker5eac2222014-06-11 12:22:55 -05002376 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy38bd7602012-09-14 13:33:53 -04002377 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002378}
Dees_Troye58d5262012-09-21 12:27:57 -04002379
2380void TWPartition::Recreate_AndSec_Folder(void) {
Dees_Troye58d5262012-09-21 12:27:57 -04002381 if (!Has_Android_Secure)
2382 return;
Dees_Troy2673cec2013-04-02 20:22:16 +00002383 LOGINFO("Creating %s: %s\n", Backup_Display_Name.c_str(), Symlink_Path.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04002384 if (!Mount(true)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002385 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Backup_Name));
Dees_Troye58d5262012-09-21 12:27:57 -04002386 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002387 LOGINFO("Recreating %s folder.\n", Backup_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002388 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05002389 mkdir(Symlink_Path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002390 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002391 }
2392}
bigbiff7cb4c332014-11-26 20:36:07 -05002393
2394uint64_t TWPartition::Get_Max_FileSize() {
2395 uint64_t maxFileSize = 0;
2396 const uint64_t constGB = (uint64_t) 1024 * 1024 * 1024;
2397 const uint64_t constTB = (uint64_t) constGB * 1024;
2398 const uint64_t constPB = (uint64_t) constTB * 1024;
2399 const uint64_t constEB = (uint64_t) constPB * 1024;
bigbiff0c532032014-12-21 13:41:26 -05002400 if (Current_File_System == "ext4")
2401 maxFileSize = 16 * constTB; //16 TB
2402 else if (Current_File_System == "vfat")
2403 maxFileSize = 4 * constGB; //4 GB
2404 else if (Current_File_System == "ntfs")
2405 maxFileSize = 256 * constTB; //256 TB
2406 else if (Current_File_System == "exfat")
2407 maxFileSize = 16 * constPB; //16 PB
2408 else if (Current_File_System == "ext3")
2409 maxFileSize = 2 * constTB; //2 TB
2410 else if (Current_File_System == "f2fs")
2411 maxFileSize = 3.94 * constTB; //3.94 TB
bigbiff7cb4c332014-11-26 20:36:07 -05002412 else
2413 maxFileSize = 100000000L;
2414 return maxFileSize - 1;
2415}
2416
Ethan Yonker472f5062016-02-25 13:47:30 -06002417bool TWPartition::Flash_Image(const string& Filename) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002418 string Restore_File_System;
2419
2420 LOGINFO("Image filename is: %s\n", Filename.c_str());
2421
2422 if (Backup_Method == FILES) {
2423 LOGERR("Cannot flash images to file systems\n");
2424 return false;
2425 } else if (!Can_Flash_Img) {
2426 LOGERR("Cannot flash images to partitions %s\n", Display_Name.c_str());
2427 return false;
2428 } else {
2429 if (!Find_Partition_Size()) {
2430 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
2431 return false;
2432 }
2433 unsigned long long image_size = TWFunc::Get_File_Size(Filename);
2434 if (image_size > Size) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002435 LOGINFO("Size (%llu bytes) of image '%s' is larger than target device '%s' (%llu bytes)\n",
Ethan Yonker96af84a2015-01-05 14:58:36 -06002436 image_size, Filename.c_str(), Actual_Block_Device.c_str(), Size);
Ethan Yonker74db1572015-10-28 12:44:49 -05002437 gui_err("img_size_err=Size of image is larger than target device");
Ethan Yonker96af84a2015-01-05 14:58:36 -06002438 return false;
2439 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002440 if (Backup_Method == DD) {
2441 if (Is_Sparse_Image(Filename)) {
2442 return Flash_Sparse_Image(Filename);
2443 }
2444 unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename));
2445 ProgressTracking pt(file_size);
2446 return Raw_Read_Write(Filename, Actual_Block_Device, file_size, &pt);
2447 } else if (Backup_Method == FLASH_UTILS) {
2448 return Flash_Image_FI(Filename, NULL);
2449 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002450 }
2451
2452 LOGERR("Unknown flash method for '%s'\n", Mount_Point.c_str());
2453 return false;
2454}
2455
Ethan Yonker472f5062016-02-25 13:47:30 -06002456bool TWPartition::Is_Sparse_Image(const string& Filename) {
HashBanged974bb2016-01-30 14:20:09 -05002457 uint32_t magic = 0;
2458 int fd = open(Filename.c_str(), O_RDONLY);
2459 if (fd < 0) {
2460 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2461 return false;
2462 }
2463 if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) {
2464 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2465 close(fd);
2466 return false;
2467 }
2468 close(fd);
Ethan Yonker472f5062016-02-25 13:47:30 -06002469 if (magic == SPARSE_HEADER_MAGIC)
2470 return true;
2471 return false;
2472}
2473
2474bool TWPartition::Flash_Sparse_Image(const string& Filename) {
2475 string Command;
2476
2477 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
2478
2479 Command = "simg2img '" + Filename + "' '" + Actual_Block_Device + "'";
Ethan Yonker96af84a2015-01-05 14:58:36 -06002480 LOGINFO("Flash command: '%s'\n", Command.c_str());
2481 TWFunc::Exec_Cmd(Command);
2482 return true;
2483}
2484
Ethan Yonker472f5062016-02-25 13:47:30 -06002485bool TWPartition::Flash_Image_FI(const string& Filename, ProgressTracking *progress) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002486 string Command;
Ethan Yonker472f5062016-02-25 13:47:30 -06002487 unsigned long long file_size;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002488
Ethan Yonker74db1572015-10-28 12:44:49 -05002489 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
Ethan Yonker472f5062016-02-25 13:47:30 -06002490 if (progress) {
2491 file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename));
2492 progress->SetPartitionSize(file_size);
2493 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002494 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
2495 Command = "erase_image " + MTD_Name;
2496 LOGINFO("Erase command: '%s'\n", Command.c_str());
2497 TWFunc::Exec_Cmd(Command);
2498 Command = "flash_image " + MTD_Name + " '" + Filename + "'";
2499 LOGINFO("Flash command: '%s'\n", Command.c_str());
2500 TWFunc::Exec_Cmd(Command);
Ethan Yonker472f5062016-02-25 13:47:30 -06002501 if (progress)
2502 progress->UpdateSize(file_size);
Ethan Yonker96af84a2015-01-05 14:58:36 -06002503 return true;
2504}
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05002505
2506void TWPartition::Change_Mount_Read_Only(bool new_value) {
2507 Mount_Read_Only = new_value;
2508}
2509
2510int TWPartition::Check_Lifetime_Writes() {
2511 bool original_read_only = Mount_Read_Only;
2512 int ret = 1;
2513
2514 Mount_Read_Only = true;
2515 if (Mount(false)) {
2516 Find_Actual_Block_Device();
2517 string block = basename(Actual_Block_Device.c_str());
2518 string file = "/sys/fs/" + Current_File_System + "/" + block + "/lifetime_write_kbytes";
2519 string result;
2520 if (TWFunc::Path_Exists(file)) {
2521 if (TWFunc::read_file(file, result) != 0) {
2522 LOGINFO("Check_Lifetime_Writes of '%s' failed to read_file\n", file.c_str());
2523 } else {
2524 LOGINFO("Check_Lifetime_Writes result: '%s'\n", result.c_str());
2525 if (result == "0") {
2526 ret = 0;
2527 }
2528 }
2529 } else {
2530 LOGINFO("Check_Lifetime_Writes file does not exist '%s'\n", file.c_str());
2531 }
2532 UnMount(true);
2533 } else {
2534 LOGINFO("Check_Lifetime_Writes failed to mount '%s'\n", Mount_Point.c_str());
2535 }
2536 Mount_Read_Only = original_read_only;
2537 return ret;
2538}
Ethan Yonker66a19492015-12-10 10:19:45 -06002539
2540int TWPartition::Decrypt_Adopted() {
2541#ifdef TW_INCLUDE_CRYPTO
2542 int ret = 1;
2543 Is_Adopted_Storage = false;
2544 string Adopted_Key_File = "";
2545
2546 if (!Removable)
2547 return ret;
2548
2549 int fd = open(Alternate_Block_Device.c_str(), O_RDONLY);
2550 if (fd < 0) {
2551 LOGINFO("failed to open '%s'\n", Alternate_Block_Device.c_str());
2552 return ret;
2553 }
2554 char type_guid[80];
2555 char part_guid[80];
2556
2557 if (gpt_disk_get_partition_info(fd, 2, type_guid, part_guid) == 0) {
2558 LOGINFO("type: '%s'\n", type_guid);
2559 LOGINFO("part: '%s'\n", part_guid);
2560 Adopted_GUID = part_guid;
2561 LOGINFO("Adopted_GUID '%s'\n", Adopted_GUID.c_str());
2562 if (strcmp(type_guid, TWGptAndroidExpand) == 0) {
2563 LOGINFO("android_expand found\n");
2564 Adopted_Key_File = "/data/misc/vold/expand_";
2565 Adopted_Key_File += part_guid;
2566 Adopted_Key_File += ".key";
2567 if (TWFunc::Path_Exists(Adopted_Key_File)) {
2568 Is_Adopted_Storage = true;
2569 /* Until we find a use case for this, I think it is safe
2570 * to disable USB Mass Storage whenever adopted storage
2571 * is present.
2572 */
2573 LOGINFO("Detected adopted storage, disabling USB mass storage mode\n");
2574 DataManager::SetValue("tw_has_usb_storage", 0);
2575 }
2576 }
2577 }
2578
2579 if (Is_Adopted_Storage) {
2580 string Adopted_Block_Device = Alternate_Block_Device + "p2";
2581 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
2582 Adopted_Block_Device = Alternate_Block_Device + "2";
2583 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
2584 LOGINFO("Adopted block device does not exist\n");
2585 goto exit;
2586 }
2587 }
2588 LOGINFO("key file is '%s', block device '%s'\n", Adopted_Key_File.c_str(), Adopted_Block_Device.c_str());
2589 char crypto_blkdev[MAXPATHLEN];
2590 std::string thekey;
2591 int fdkey = open(Adopted_Key_File.c_str(), O_RDONLY);
2592 if (fdkey < 0) {
2593 LOGINFO("failed to open key file\n");
2594 goto exit;
2595 }
2596 char buf[512];
2597 ssize_t n;
2598 while ((n = read(fdkey, &buf[0], sizeof(buf))) > 0) {
2599 thekey.append(buf, n);
2600 }
2601 close(fdkey);
2602 unsigned char* key = (unsigned char*) thekey.data();
2603 cryptfs_revert_ext_volume(part_guid);
2604
2605 ret = cryptfs_setup_ext_volume(part_guid, Adopted_Block_Device.c_str(), key, thekey.size(), crypto_blkdev);
2606 if (ret == 0) {
2607 LOGINFO("adopted storage new block device: '%s'\n", crypto_blkdev);
2608 Decrypted_Block_Device = crypto_blkdev;
2609 Is_Decrypted = true;
2610 Is_Encrypted = true;
2611 Find_Actual_Block_Device();
2612 if (!Mount(false)) {
2613 LOGERR("Failed to mount decrypted adopted storage device\n");
2614 Is_Decrypted = false;
2615 Is_Encrypted = false;
2616 cryptfs_revert_ext_volume(part_guid);
2617 ret = 1;
2618 } else {
Ethan Yonkerfcf3f242016-02-16 12:30:26 -06002619 UnMount(false);
2620 Has_Android_Secure = false;
2621 Symlink_Path = "";
2622 Symlink_Mount_Point = "";
2623 Backup_Name = Mount_Point.substr(1);
2624 Backup_Path = Mount_Point;
2625 TWPartition* sdext = PartitionManager.Find_Partition_By_Path("/sd-ext");
2626 if (sdext && sdext->Actual_Block_Device == Adopted_Block_Device) {
2627 LOGINFO("Removing /sd-ext from partition list due to adopted storage\n");
2628 PartitionManager.Remove_Partition_By_Path("/sd-ext");
2629 }
Ethan Yonker66a19492015-12-10 10:19:45 -06002630 Setup_Data_Media();
2631 Recreate_Media_Folder();
2632 Wipe_Available_in_GUI = true;
2633 Wipe_During_Factory_Reset = true;
2634 Can_Be_Backed_Up = true;
2635 Can_Encrypt_Backup = true;
2636 Use_Userdata_Encryption = true;
2637 Is_Storage = true;
2638 Storage_Name = "Adopted Storage";
2639 Is_SubPartition = true;
2640 SubPartition_Of = "/data";
2641 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
2642 DataManager::SetValue("tw_has_adopted_storage", 1);
2643 }
2644 } else {
2645 LOGERR("Failed to setup adopted storage decryption\n");
2646 }
2647 }
2648exit:
2649 return ret;
2650#else
2651 LOGINFO("Decrypt_Adopted: no crypto support\n");
2652 return 1;
2653#endif
2654}
2655
2656void TWPartition::Revert_Adopted() {
2657#ifdef TW_INCLUDE_CRYPTO
2658 if (!Adopted_GUID.empty()) {
2659 PartitionManager.Remove_MTP_Storage(Mount_Point);
2660 UnMount(false);
2661 cryptfs_revert_ext_volume(Adopted_GUID.c_str());
2662 Is_Adopted_Storage = false;
2663 Is_Encrypted = false;
2664 Is_Decrypted = false;
2665 Decrypted_Block_Device = "";
2666 Find_Actual_Block_Device();
2667 Wipe_During_Factory_Reset = false;
2668 Can_Be_Backed_Up = false;
2669 Can_Encrypt_Backup = false;
2670 Use_Userdata_Encryption = false;
2671 Is_SubPartition = false;
2672 SubPartition_Of = "";
2673 Has_Data_Media = false;
2674 Storage_Path = Mount_Point;
2675 if (!Symlink_Mount_Point.empty()) {
2676 TWPartition* Dat = PartitionManager.Find_Partition_By_Path("/data");
2677 if (Dat) {
2678 Dat->UnMount(false);
2679 Dat->Symlink_Mount_Point = Symlink_Mount_Point;
2680 }
2681 Symlink_Mount_Point = "";
2682 }
2683 }
2684#else
2685 LOGINFO("Revert_Adopted: no crypto support\n");
2686#endif
2687}