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)<