blob: 3957c6542c28dd0b50d368e3060269a0e996c54c [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
bigbiff bigbiff56cf5642016-08-19 17:43:45 -04002 Copyright 2013 to 2017 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>
bigbiffce8f83c2015-12-12 18:30:21 -050028#include <zlib.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050029#include <iostream>
30#include <sstream>
Ethan Yonker66a19492015-12-10 10:19:45 -060031#include <sys/param.h>
Ethan Yonker472f5062016-02-25 13:47:30 -060032#include <fcntl.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040033
Dees_Troy657c3092012-09-10 20:32:10 -040034#ifdef TW_INCLUDE_CRYPTO
35 #include "cutils/properties.h"
36#endif
37
bigbiff7b4c7a62015-01-01 19:44:14 -050038#include "libblkid/include/blkid.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040039#include "variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040042#include "data.hpp"
Dees_Troy43d8b002012-09-17 16:00:01 -040043#include "twrp-functions.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050044#include "twrpTar.hpp"
Ethan Yonker3fdcda42016-11-30 12:29:37 -060045#include "exclude.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"
bigbiffce8f83c2015-12-12 18:30:21 -050049#include "adbbu/libtwadbbu.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040050extern "C" {
Dees_Troy38bd7602012-09-14 13:33:53 -040051 #include "mtdutils/mtdutils.h"
52 #include "mtdutils/mounts.h"
Dees_Troya95f55c2013-08-17 13:14:43 +000053#ifdef USE_EXT4
Ethan Yonker8373cfe2017-09-08 06:50:54 -050054 // #include "make_ext4fs.h" TODO need ifdef for android8
55 #include <ext4_utils/make_ext4fs.h>
Dees_Troya95f55c2013-08-17 13:14:43 +000056#endif
Ethan Yonker71413f42014-02-26 13:36:08 -060057
58#ifdef TW_INCLUDE_CRYPTO
Ethan Yonker253368a2014-11-25 15:00:52 -060059 #include "crypto/lollipop/cryptfs.h"
Ethan Yonker66a19492015-12-10 10:19:45 -060060 #include "gpt/gpt.h"
Ethan Yonkerbd7492d2016-12-07 13:55:01 -060061 #ifdef TW_INCLUDE_FBE
62 #include "crypto/ext4crypt/Decrypt.h"
Ethan Yonkerbd7492d2016-12-07 13:55:01 -060063 #endif
Ethan Yonkerbc85b632015-08-09 12:48:14 -050064#else
65 #define CRYPT_FOOTER_OFFSET 0x4000
Ethan Yonker71413f42014-02-26 13:36:08 -060066#endif
Dees_Troy5bf43922012-09-07 16:07:55 -040067}
Matt Mower87413642017-01-17 21:14:46 -060068#include <selinux/selinux.h>
Ethan Yonkerf27497f2014-02-09 11:48:33 -060069#include <selinux/label.h>
Dees Troy4159aed2014-02-28 17:24:43 +000070#ifdef HAVE_CAPABILITIES
71#include <sys/capability.h>
72#include <sys/xattr.h>
73#include <linux/xattr.h>
74#endif
HashBanged974bb2016-01-30 14:20:09 -050075#include <sparse_format.h>
Ethan Yonker472f5062016-02-25 13:47:30 -060076#include "progresstracking.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040077
bigbiff bigbiff9c754052013-01-09 09:09:08 -050078using namespace std;
79
Ethan Yonker6e8c27a2016-12-22 17:55:57 -060080static int auto_index = 0; // v2 fstab allows you to specify a mount point of "auto" with no /. These items are given a mount point of /auto* where * == auto_index
81
Dees_Troya95f55c2013-08-17 13:14:43 +000082extern struct selabel_handle *selinux_handle;
Ethan Yonker6277c792014-09-15 14:54:30 -050083extern bool datamedia;
Dees_Troya95f55c2013-08-17 13:14:43 +000084
Hashcode62bd9e02013-11-19 21:59:42 -080085struct flag_list {
86 const char *name;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -060087 unsigned long flag;
Hashcode62bd9e02013-11-19 21:59:42 -080088};
89
Matt Mower4ab42b12016-04-21 13:52:18 -050090const struct flag_list mount_flags[] = {
Ethan Yonker6e8c27a2016-12-22 17:55:57 -060091 { "noatime", MS_NOATIME },
92 { "noexec", MS_NOEXEC },
93 { "nosuid", MS_NOSUID },
94 { "nodev", MS_NODEV },
95 { "nodiratime", MS_NODIRATIME },
96 { "ro", MS_RDONLY },
97 { "rw", 0 },
98 { "remount", MS_REMOUNT },
99 { "bind", MS_BIND },
100 { "rec", MS_REC },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000101#ifdef MS_UNBINDABLE
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600102 { "unbindable", MS_UNBINDABLE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000103#endif
104#ifdef MS_PRIVATE
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600105 { "private", MS_PRIVATE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000106#endif
107#ifdef MS_SLAVE
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600108 { "slave", MS_SLAVE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000109#endif
110#ifdef MS_SHARED
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600111 { "shared", MS_SHARED },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000112#endif
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600113 { "sync", MS_SYNCHRONOUS },
114 { 0, 0 },
115};
116
117const char *ignored_mount_items[] = {
118 "defaults=",
119 "errors=",
120 NULL
Hashcode62bd9e02013-11-19 21:59:42 -0800121};
122
Matt Mower2416a502016-04-12 19:54:46 -0500123enum TW_FSTAB_FLAGS {
124 TWFLAG_DEFAULTS, // Retain position
125 TWFLAG_ANDSEC,
126 TWFLAG_BACKUP,
127 TWFLAG_BACKUPNAME,
128 TWFLAG_BLOCKSIZE,
129 TWFLAG_CANBEWIPED,
130 TWFLAG_CANENCRYPTBACKUP,
131 TWFLAG_DISPLAY,
132 TWFLAG_ENCRYPTABLE,
133 TWFLAG_FLASHIMG,
134 TWFLAG_FORCEENCRYPT,
135 TWFLAG_FSFLAGS,
136 TWFLAG_IGNOREBLKID,
137 TWFLAG_LENGTH,
138 TWFLAG_MOUNTTODECRYPT,
139 TWFLAG_REMOVABLE,
140 TWFLAG_RETAINLAYOUTVERSION,
141 TWFLAG_SETTINGSSTORAGE,
142 TWFLAG_STORAGE,
143 TWFLAG_STORAGENAME,
144 TWFLAG_SUBPARTITIONOF,
145 TWFLAG_SYMLINK,
146 TWFLAG_USERDATAENCRYPTBACKUP,
147 TWFLAG_USERMRF,
148 TWFLAG_WIPEDURINGFACTORYRESET,
149 TWFLAG_WIPEINGUI,
Ethan Yonker1b190162016-12-05 15:25:19 -0600150 TWFLAG_SLOTSELECT,
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600151 TWFLAG_WAIT,
152 TWFLAG_VERIFY,
153 TWFLAG_CHECK,
154 TWFLAG_ALTDEVICE,
155 TWFLAG_NOTRIM,
156 TWFLAG_VOLDMANAGED,
157 TWFLAG_FORMATTABLE,
158 TWFLAG_RESIZE,
Matt Mower2416a502016-04-12 19:54:46 -0500159};
160
161/* Flags without a trailing '=' are considered dual format flags and can be
162 * written as either 'flagname' or 'flagname=', where the character following
163 * the '=' is Y,y,1 for true and false otherwise.
164 */
165const struct flag_list tw_flags[] = {
166 { "andsec", TWFLAG_ANDSEC },
167 { "backup", TWFLAG_BACKUP },
168 { "backupname=", TWFLAG_BACKUPNAME },
169 { "blocksize=", TWFLAG_BLOCKSIZE },
170 { "canbewiped", TWFLAG_CANBEWIPED },
171 { "canencryptbackup", TWFLAG_CANENCRYPTBACKUP },
172 { "defaults", TWFLAG_DEFAULTS },
173 { "display=", TWFLAG_DISPLAY },
174 { "encryptable=", TWFLAG_ENCRYPTABLE },
175 { "flashimg", TWFLAG_FLASHIMG },
176 { "forceencrypt=", TWFLAG_FORCEENCRYPT },
177 { "fsflags=", TWFLAG_FSFLAGS },
178 { "ignoreblkid", TWFLAG_IGNOREBLKID },
179 { "length=", TWFLAG_LENGTH },
180 { "mounttodecrypt", TWFLAG_MOUNTTODECRYPT },
181 { "removable", TWFLAG_REMOVABLE },
182 { "retainlayoutversion", TWFLAG_RETAINLAYOUTVERSION },
183 { "settingsstorage", TWFLAG_SETTINGSSTORAGE },
184 { "storage", TWFLAG_STORAGE },
185 { "storagename=", TWFLAG_STORAGENAME },
186 { "subpartitionof=", TWFLAG_SUBPARTITIONOF },
187 { "symlink=", TWFLAG_SYMLINK },
188 { "userdataencryptbackup", TWFLAG_USERDATAENCRYPTBACKUP },
189 { "usermrf", TWFLAG_USERMRF },
190 { "wipeduringfactoryreset", TWFLAG_WIPEDURINGFACTORYRESET },
191 { "wipeingui", TWFLAG_WIPEINGUI },
Ethan Yonker1b190162016-12-05 15:25:19 -0600192 { "slotselect", TWFLAG_SLOTSELECT },
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600193 { "wait", TWFLAG_WAIT },
194 { "verify", TWFLAG_VERIFY },
195 { "check", TWFLAG_CHECK },
196 { "altdevice", TWFLAG_ALTDEVICE },
197 { "notrim", TWFLAG_NOTRIM },
198 { "voldmanaged=", TWFLAG_VOLDMANAGED },
199 { "formattable", TWFLAG_FORMATTABLE },
200 { "resize", TWFLAG_RESIZE },
Matt Mower2416a502016-04-12 19:54:46 -0500201 { 0, 0 },
202};
203
that9e0593e2014-10-08 00:01:24 +0200204TWPartition::TWPartition() {
Dees_Troy51a0e822012-09-05 15:24:24 -0400205 Can_Be_Mounted = false;
206 Can_Be_Wiped = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500207 Can_Be_Backed_Up = false;
Vojtech Bocek1dc30982013-08-30 21:49:30 +0200208 Use_Rm_Rf = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400209 Wipe_During_Factory_Reset = false;
210 Wipe_Available_in_GUI = false;
211 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -0400212 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400213 SubPartition_Of = "";
214 Symlink_Path = "";
215 Symlink_Mount_Point = "";
216 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -0400217 Backup_Path = "";
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600218 Wildcard_Block_Device = false;
219 Sysfs_Entry = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400220 Actual_Block_Device = "";
221 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400222 Alternate_Block_Device = "";
223 Removable = false;
224 Is_Present = false;
225 Length = 0;
226 Size = 0;
227 Used = 0;
228 Free = 0;
229 Backup_Size = 0;
230 Can_Be_Encrypted = false;
231 Is_Encrypted = false;
232 Is_Decrypted = false;
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600233 Is_FBE = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600234 Mount_To_Decrypt = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400235 Decrypted_Block_Device = "";
236 Display_Name = "";
Dees_Troya13d74f2013-03-24 08:54:55 -0500237 Backup_Display_Name = "";
238 Storage_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400239 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -0400240 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400241 MTD_Name = "";
bigbiffce8f83c2015-12-12 18:30:21 -0500242 Backup_Method = BM_NONE;
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 Can_Encrypt_Backup = false;
244 Use_Userdata_Encryption = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400245 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -0400246 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400247 Is_Storage = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500248 Is_Settings_Storage = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400249 Storage_Path = "";
250 Current_File_System = "";
251 Fstab_File_System = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800252 Mount_Flags = 0;
253 Mount_Options = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400254 Format_Block_Size = 0;
Dees_Troy68cab492012-12-12 19:29:35 +0000255 Ignore_Blkid = false;
Dees_Troy16c2b312013-01-15 16:51:18 +0000256 Retain_Layout_Version = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600257 Crypto_Key_Location = "footer";
Ethan Yonker726a0202014-12-16 20:01:38 -0600258 MTP_Storage_ID = 0;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600259 Can_Flash_Img = false;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500260 Mount_Read_Only = false;
Ethan Yonker66a19492015-12-10 10:19:45 -0600261 Is_Adopted_Storage = false;
262 Adopted_GUID = "";
Ethan Yonker1b190162016-12-05 15:25:19 -0600263 SlotSelect = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400264}
265
266TWPartition::~TWPartition(void) {
267 // Do nothing
268}
269
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600270bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags) {
Matt Mower2b2dd152016-04-26 11:24:08 -0500271 char full_line[MAX_FSTAB_LINE_LENGTH];
Matt Mower2416a502016-04-12 19:54:46 -0500272 char twflags[MAX_FSTAB_LINE_LENGTH] = "";
Dees_Troy5bf43922012-09-07 16:07:55 -0400273 char* ptr;
Matt Mower2b2dd152016-04-26 11:24:08 -0500274 int line_len = strlen(fstab_line), index = 0, item_index = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500275 bool skip = false;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600276 int fstab_version = 1, mount_point_index = 0, fs_index = 1, block_device_index = 2;
277 TWPartition *additional_entry = NULL;
278 std::map<string, Flags_Map>::iterator it;
Dees_Troy5bf43922012-09-07 16:07:55 -0400279
Matt Mower2b2dd152016-04-26 11:24:08 -0500280 strlcpy(full_line, fstab_line, sizeof(full_line));
Dees_Troy51127312012-09-08 13:08:49 -0400281 for (index = 0; index < line_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500282 if (full_line[index] == 34)
283 skip = !skip;
284 if (!skip && full_line[index] <= 32)
Dees_Troy5bf43922012-09-07 16:07:55 -0400285 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400286 }
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600287 if (line_len < 10)
288 return false; // There can't possibly be a valid fstab line that is less than 10 chars
289 if (strncmp(fstab_line, "/dev/", strlen("/dev/")) == 0 || strncmp(fstab_line, "/devices/", strlen("/devices/")) == 0) {
290 fstab_version = 2;
291 block_device_index = 0;
292 mount_point_index = 1;
293 fs_index = 2;
294 }
295
296 index = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -0400297 while (index < line_len) {
298 while (index < line_len && full_line[index] == '\0')
299 index++;
300 if (index >= line_len)
301 continue;
302 ptr = full_line + index;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600303 if (item_index == mount_point_index) {
304 Mount_Point = ptr;
305 if (fstab_version == 2) {
306 additional_entry = PartitionManager.Find_Partition_By_Path(Mount_Point);
307 if (additional_entry) {
308 LOGINFO("Found an additional entry for '%s'\n", Mount_Point.c_str());
309 }
310 }
311 LOGINFO("Processing '%s'\n", Mount_Point.c_str());
312 Backup_Path = Mount_Point;
313 Storage_Path = Mount_Point;
314 Display_Name = ptr + 1;
315 Backup_Display_Name = Display_Name;
316 Storage_Name = Display_Name;
317 item_index++;
318 } else if (item_index == fs_index) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400319 // File System
320 Fstab_File_System = ptr;
321 Current_File_System = ptr;
322 item_index++;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600323 } else if (item_index == block_device_index) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400324 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400325 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
Dees_Troy094207a2012-09-26 12:00:39 -0400326 MTD_Name = ptr;
327 Find_MTD_Block_Device(MTD_Name);
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400328 } else if (Fstab_File_System == "bml") {
329 if (Mount_Point == "/boot")
330 MTD_Name = "boot";
331 else if (Mount_Point == "/recovery")
332 MTD_Name = "recovery";
333 Primary_Block_Device = ptr;
334 if (*ptr != '/')
Dees_Troy2673cec2013-04-02 20:22:16 +0000335 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 -0400336 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400337 if (Display_Error)
Matt Mower2b2dd152016-04-26 11:24:08 -0500338 LOGERR("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
Dees_Troy5bf43922012-09-07 16:07:55 -0400339 else
Matt Mower2b2dd152016-04-26 11:24:08 -0500340 LOGINFO("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
Matt Mower72c87ce2016-04-26 14:34:56 -0500341 return false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400342 } else {
343 Primary_Block_Device = ptr;
344 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400345 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400346 item_index++;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600347 } else if (item_index > 2) {
348 if (fstab_version == 2) {
349 if (item_index == 3) {
350 Process_FS_Flags(ptr);
351 if (additional_entry) {
352 additional_entry->Save_FS_Flags(Fstab_File_System, Mount_Flags, Mount_Options);
353 return false; // We save the extra fs flags in the other partition entry and by returning false, this entry will be deleted
354 }
355 } else {
356 strlcpy(twflags, ptr, sizeof(twflags));
357 }
358 item_index++;
359 } else if (*ptr == '/') { // v2 fstab does not allow alternate block devices
Dees_Troy5bf43922012-09-07 16:07:55 -0400360 // Alternate Block Device
361 Alternate_Block_Device = ptr;
362 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
363 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
364 // Partition length
365 ptr += 7;
366 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400367 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
368 // Custom flags, save for later so that new values aren't overwritten by defaults
369 ptr += 6;
Matt Mower2416a502016-04-12 19:54:46 -0500370 strlcpy(twflags, ptr, sizeof(twflags));
Dees_Troy38bd7602012-09-14 13:33:53 -0400371 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
372 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400373 } else {
374 // Unhandled data
Matt Mower2b2dd152016-04-26 11:24:08 -0500375 LOGINFO("Unhandled fstab information '%s' in fstab line '%s'\n", ptr, fstab_line);
Dees_Troy5bf43922012-09-07 16:07:55 -0400376 }
377 }
378 while (index < line_len && full_line[index] != '\0')
379 index++;
380 }
381
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600382 // override block devices from the v2 fstab with the ones we read from the twrp.flags file in case they are different
383 if (fstab_version == 2 && twrp_flags && twrp_flags->size() > 0) {
384 it = twrp_flags->find(Mount_Point);
385 if (it != twrp_flags->end()) {
386 if (!it->second.Primary_Block_Device.empty()) {
387 Primary_Block_Device = it->second.Primary_Block_Device;
388 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
389 }
390 if (!it->second.Alternate_Block_Device.empty()) {
391 Alternate_Block_Device = it->second.Alternate_Block_Device;
392 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
393 }
394 }
395 }
396
397 if (strncmp(fstab_line, "/devices/", strlen("/devices/")) == 0) {
398 Sysfs_Entry = Primary_Block_Device;
399 Primary_Block_Device = "";
400 Is_Storage = true;
401 Removable = true;
402 Wipe_Available_in_GUI = true;
403 Wildcard_Block_Device = true;
404 }
405 if (Primary_Block_Device.find("*") != string::npos)
406 Wildcard_Block_Device = true;
407
408 if (Mount_Point == "auto") {
409 Mount_Point = "/auto";
410 char autoi[5];
411 sprintf(autoi, "%i", auto_index);
412 Mount_Point += autoi;
413 Backup_Path = Mount_Point;
414 Storage_Path = Mount_Point;
415 auto_index++;
416 Setup_File_System(Display_Error);
417 Display_Name = "Storage";
418 Backup_Display_Name = Display_Name;
419 Storage_Name = Display_Name;
420 Can_Be_Backed_Up = false;
421 Wipe_Available_in_GUI = true;
422 Is_Storage = true;
423 Removable = true;
424 Wipe_Available_in_GUI = true;
425 } else if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400426 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000427 LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400428 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000429 LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Matt Mower72c87ce2016-04-26 14:34:56 -0500430 return false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400431 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400432 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400433 Setup_File_System(Display_Error);
434 if (Mount_Point == "/system") {
435 Display_Name = "System";
Dees_Troya13d74f2013-03-24 08:54:55 -0500436 Backup_Display_Name = Display_Name;
437 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400438 Wipe_Available_in_GUI = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500439 Can_Be_Backed_Up = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500440 Mount_Read_Only = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400441 } else if (Mount_Point == "/data") {
442 Display_Name = "Data";
Dees_Troya13d74f2013-03-24 08:54:55 -0500443 Backup_Display_Name = Display_Name;
444 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400445 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400446 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500447 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000448 Can_Encrypt_Backup = true;
449 Use_Userdata_Encryption = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400450 } else if (Mount_Point == "/cache") {
451 Display_Name = "Cache";
Dees_Troya13d74f2013-03-24 08:54:55 -0500452 Backup_Display_Name = Display_Name;
453 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400454 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400455 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500456 Can_Be_Backed_Up = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400457 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400458 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400459 Display_Name = "DataData";
Dees_Troya13d74f2013-03-24 08:54:55 -0500460 Backup_Display_Name = Display_Name;
461 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400462 Is_SubPartition = true;
463 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400464 DataManager::SetValue(TW_HAS_DATADATA, 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500465 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000466 Can_Encrypt_Backup = true;
467 Use_Userdata_Encryption = false; // This whole partition should be encrypted
Dees_Troy5bf43922012-09-07 16:07:55 -0400468 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400469 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400470 Display_Name = "SD-Ext";
Dees_Troya13d74f2013-03-24 08:54:55 -0500471 Backup_Display_Name = Display_Name;
472 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400473 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400474 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500475 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000476 Can_Encrypt_Backup = true;
477 Use_Userdata_Encryption = true;
Dees_Troy2c50e182012-09-26 20:05:28 -0400478 } else if (Mount_Point == "/boot") {
479 Display_Name = "Boot";
Dees_Troya13d74f2013-03-24 08:54:55 -0500480 Backup_Display_Name = Display_Name;
Dees_Troy2c50e182012-09-26 20:05:28 -0400481 DataManager::SetValue("tw_boot_is_mountable", 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500482 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500483 } else if (Mount_Point == "/vendor") {
484 Display_Name = "Vendor";
485 Backup_Display_Name = Display_Name;
486 Storage_Name = Display_Name;
487 Mount_Read_Only = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400488 }
489#ifdef TW_EXTERNAL_STORAGE_PATH
490 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
491 Is_Storage = true;
492 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
Dees_Troyc51f1f92012-09-20 15:32:13 -0400493 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500494 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400495#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000496 if (Mount_Point == "/sdcard" || Mount_Point == "/external_sd" || Mount_Point == "/external_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400497 Is_Storage = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400498 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500499 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400500#endif
Dees_Troyb05ddee2013-01-28 20:24:50 +0000501 }
Dees_Troy8170a922012-09-18 15:40:25 -0400502#ifdef TW_INTERNAL_STORAGE_PATH
503 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
504 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500505 Is_Settings_Storage = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400506 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troya13d74f2013-03-24 08:54:55 -0500507 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400508 }
509#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000510 if (Mount_Point == "/emmc" || Mount_Point == "/internal_sd" || Mount_Point == "/internal_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400511 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500512 Is_Settings_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500513 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400514 }
515#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400516 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400517 Find_Actual_Block_Device();
Ethan Yonker1b190162016-12-05 15:25:19 -0600518 Setup_Image();
Dees_Troya13d74f2013-03-24 08:54:55 -0500519 if (Mount_Point == "/boot") {
520 Display_Name = "Boot";
521 Backup_Display_Name = Display_Name;
522 Can_Be_Backed_Up = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600523 Can_Flash_Img = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500524 } else if (Mount_Point == "/recovery") {
525 Display_Name = "Recovery";
526 Backup_Display_Name = Display_Name;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600527 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500528 } else if (Mount_Point == "/system_image") {
529 Display_Name = "System Image";
530 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500531 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500532 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500533 } else if (Mount_Point == "/vendor_image") {
534 Display_Name = "Vendor Image";
535 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500536 Can_Flash_Img = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500537 Can_Be_Backed_Up = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500538 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400539 }
540
Matt Mower2416a502016-04-12 19:54:46 -0500541 // Process TWRP fstab flags
542 if (strlen(twflags) > 0) {
543 string Prev_Display_Name = Display_Name;
544 string Prev_Storage_Name = Storage_Name;
545 string Prev_Backup_Display_Name = Backup_Display_Name;
546 Display_Name = "";
547 Storage_Name = "";
548 Backup_Display_Name = "";
549
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600550 Process_TW_Flags(twflags, (fstab_version == 1), fstab_version);
551 Save_FS_Flags(Fstab_File_System, Mount_Flags, Mount_Options);
Matt Mower2416a502016-04-12 19:54:46 -0500552
553 bool has_display_name = !Display_Name.empty();
554 bool has_storage_name = !Storage_Name.empty();
555 bool has_backup_name = !Backup_Display_Name.empty();
556 if (!has_display_name) Display_Name = Prev_Display_Name;
557 if (!has_storage_name) Storage_Name = Prev_Storage_Name;
558 if (!has_backup_name) Backup_Display_Name = Prev_Backup_Display_Name;
559
560 if (has_display_name && !has_storage_name)
561 Storage_Name = Display_Name;
562 if (!has_display_name && has_storage_name)
563 Display_Name = Storage_Name;
564 if (has_display_name && !has_backup_name && Backup_Display_Name != "Android Secure")
565 Backup_Display_Name = Display_Name;
566 if (!has_display_name && has_backup_name)
567 Display_Name = Backup_Display_Name;
568 }
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600569
570 if (fstab_version == 2 && twrp_flags && twrp_flags->size() > 0) {
571 it = twrp_flags->find(Mount_Point);
572 if (it != twrp_flags->end()) {
573 char twrpflags[MAX_FSTAB_LINE_LENGTH] = "";
574 int skip = 0;
575 string Flags = it->second.Flags;
576 strcpy(twrpflags, Flags.c_str());
577 if (strlen(twrpflags) > strlen("flags=") && strncmp(twrpflags, "flags=", strlen("flags=")) == 0)
578 skip += strlen("flags=");
579 char* flagptr = twrpflags;
580 flagptr += skip;
581 Process_TW_Flags(flagptr, Display_Error, 1); // Forcing the fstab to ver 1 because this data is coming from the /etc/twrp.flags which should be using the TWRP v1 flags format
582 }
583 }
Dees_Troy51127312012-09-08 13:08:49 -0400584 return true;
585}
586
Matt Mower72c87ce2016-04-26 14:34:56 -0500587void TWPartition::Partition_Post_Processing(bool Display_Error) {
588 if (Mount_Point == "/data")
589 Setup_Data_Partition(Display_Error);
590 else if (Mount_Point == "/cache")
591 Setup_Cache_Partition(Display_Error);
592}
593
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600594void TWPartition::ExcludeAll(const string& path) {
595 backup_exclusions.add_absolute_dir(path);
596 wipe_exclusions.add_absolute_dir(path);
597}
598
Matt Mower72c87ce2016-04-26 14:34:56 -0500599void TWPartition::Setup_Data_Partition(bool Display_Error) {
600 if (Mount_Point != "/data")
601 return;
602
603 // Ensure /data is not mounted as tmpfs for qcom hardware decrypt
604 UnMount(false);
605
606#ifdef TW_INCLUDE_CRYPTO
607 if (datamedia)
608 Setup_Data_Media();
609 Can_Be_Encrypted = true;
610 char crypto_blkdev[255];
611 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
612 if (strcmp(crypto_blkdev, "error") != 0) {
613 DataManager::SetValue(TW_IS_DECRYPTED, 1);
614 Is_Encrypted = true;
615 Is_Decrypted = true;
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600616 Is_FBE = false;
617 DataManager::SetValue(TW_IS_FBE, 0);
Matt Mower72c87ce2016-04-26 14:34:56 -0500618 Decrypted_Block_Device = crypto_blkdev;
619 LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
620 } else if (!Mount(false)) {
621 if (Is_Present) {
622 set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
623 if (cryptfs_check_footer() == 0) {
624 Is_Encrypted = true;
625 Is_Decrypted = false;
626 Can_Be_Mounted = false;
627 Current_File_System = "emmc";
Ethan Yonker1b190162016-12-05 15:25:19 -0600628 Setup_Image();
Matt Mower72c87ce2016-04-26 14:34:56 -0500629 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
630 DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
631 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
632 DataManager::SetValue("tw_crypto_display", "");
633 } else {
634 gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
635 }
636 } else {
637 LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
638 }
639 } else {
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600640 if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
641 LOGINFO("File Based Encryption is present\n");
642#ifdef TW_INCLUDE_FBE
643 ExcludeAll(Mount_Point + "/convert_fbe");
644 ExcludeAll(Mount_Point + "/unencrypted");
645 //ExcludeAll(Mount_Point + "/system/users/0"); // we WILL need to retain some of this if multiple users are present or we just need to delete more folders for the extra users somewhere else
646 ExcludeAll(Mount_Point + "/misc/vold/user_keys");
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600647 //ExcludeAll(Mount_Point + "/system_ce");
648 //ExcludeAll(Mount_Point + "/system_de");
649 //ExcludeAll(Mount_Point + "/misc_ce");
650 //ExcludeAll(Mount_Point + "/misc_de");
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600651 ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
652 ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
653 ExcludeAll(Mount_Point + "/system/locksettings.db");
654 //ExcludeAll(Mount_Point + "/system/locksettings.db-shm"); // don't seem to need this one, but the other 2 are needed
655 ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600656 //ExcludeAll(Mount_Point + "/user_de");
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600657 //ExcludeAll(Mount_Point + "/misc/profiles/cur/0"); // might be important later
658 ExcludeAll(Mount_Point + "/misc/gatekeeper");
Ethan Yonkerfefe5912017-09-30 22:22:13 -0500659 ExcludeAll(Mount_Point + "/misc/keystore");
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600660 ExcludeAll(Mount_Point + "/drm/kek.dat");
Ethan Yonkerfefe5912017-09-30 22:22:13 -0500661 ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600662 int retry_count = 3;
663 while (!Decrypt_DE() && --retry_count)
664 usleep(2000);
665 if (retry_count > 0) {
666 property_set("ro.crypto.state", "encrypted");
667 Is_Encrypted = true;
668 Is_Decrypted = false;
669 Is_FBE = true;
670 DataManager::SetValue(TW_IS_FBE, 1);
671 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
672 string filename;
Ethan Yonkerfefe5912017-09-30 22:22:13 -0500673 int pwd_type = Get_Password_Type(0, filename);
674 if (pwd_type < 0) {
675 LOGERR("This TWRP does not have synthetic password decrypt support\n");
676 pwd_type = 0; // default password
677 }
678 DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type);
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600679 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
680 DataManager::SetValue("tw_crypto_display", "");
681 }
682#else
683 LOGERR("FBE found but FBE support not present in TWRP\n");
684#endif
685 } else {
686 // Filesystem is not encrypted and the mount succeeded, so return to
687 // the original unmounted state
688 UnMount(false);
689 }
Matt Mower72c87ce2016-04-26 14:34:56 -0500690 }
691 if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
692 Setup_Data_Media();
693 Recreate_Media_Folder();
694 }
695#else
696 if (datamedia) {
697 Setup_Data_Media();
698 Recreate_Media_Folder();
699 }
700#endif
701}
702
703void TWPartition::Setup_Cache_Partition(bool Display_Error __unused) {
704 if (Mount_Point != "/cache")
705 return;
706
707 if (!Mount(true))
708 return;
709
710 if (!TWFunc::Path_Exists("/cache/recovery/.")) {
711 LOGINFO("Recreating /cache/recovery folder\n");
712 if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
713 LOGERR("Could not create /cache/recovery\n");
714 }
715}
716
Matt Mower4ab42b12016-04-21 13:52:18 -0500717void TWPartition::Process_FS_Flags(const char *str) {
718 char *options = strdup(str);
719 char *ptr, *savep;
Hashcode62bd9e02013-11-19 21:59:42 -0800720
Matt Mower4ab42b12016-04-21 13:52:18 -0500721 Mount_Options = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800722
Matt Mower4ab42b12016-04-21 13:52:18 -0500723 // Avoid issues with potentially nested strtok by using strtok_r
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600724 for (ptr = strtok_r(options, ",", &savep); ptr; ptr = strtok_r(NULL, ",", &savep)) {
725 char *equals = strstr(ptr, "=");
726 size_t name_len;
Matt Mower4ab42b12016-04-21 13:52:18 -0500727
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600728 if (!equals)
729 name_len = strlen(ptr);
730 else
731 name_len = equals - ptr;
732
733 // There are some flags that we want to ignore in TWRP
734 bool found_match = false;
735 for (const char** ignored_mount_item = ignored_mount_items; *ignored_mount_item; ignored_mount_item++) {
736 if (strncmp(ptr, *ignored_mount_item, name_len) == 0) {
737 found_match = true;
Hashcode62bd9e02013-11-19 21:59:42 -0800738 break;
739 }
740 }
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600741 if (found_match)
742 continue;
Hashcode62bd9e02013-11-19 21:59:42 -0800743
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600744 // mount_flags are never postfixed by '='
745 if (!equals) {
746 const struct flag_list* mount_flag = mount_flags;
747 for (; mount_flag->name; mount_flag++) {
748 if (strcmp(ptr, mount_flag->name) == 0) {
749 if (mount_flag->flag == MS_RDONLY)
750 Mount_Read_Only = true;
751 else
752 Mount_Flags |= (unsigned)mount_flag->flag;
753 found_match = true;
754 break;
755 }
756 }
757 if (found_match)
758 continue;
Matt Mower4ab42b12016-04-21 13:52:18 -0500759 }
760
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600761 // If we aren't ignoring this flag and it's not a mount flag, then it must be a mount option
762 if (!Mount_Options.empty())
763 Mount_Options += ",";
764 Mount_Options += ptr;
Matt Mower4ab42b12016-04-21 13:52:18 -0500765 }
766 free(options);
Hashcode62bd9e02013-11-19 21:59:42 -0800767}
768
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600769void TWPartition::Save_FS_Flags(const string& local_File_System, int local_Mount_Flags, const string& local_Mount_Options) {
770 partition_fs_flags_struct flags;
771 flags.File_System = local_File_System;
772 flags.Mount_Flags = local_Mount_Flags;
773 flags.Mount_Options = local_Mount_Options;
774 fs_flags.push_back(flags);
775}
776
Matt Mower2416a502016-04-12 19:54:46 -0500777void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool val) {
778 switch (flag) {
779 case TWFLAG_ANDSEC:
780 Has_Android_Secure = val;
781 break;
782 case TWFLAG_BACKUP:
783 Can_Be_Backed_Up = val;
784 break;
785 case TWFLAG_BACKUPNAME:
786 Backup_Display_Name = str;
787 break;
788 case TWFLAG_BLOCKSIZE:
789 Format_Block_Size = (unsigned long)(atol(str));
790 break;
791 case TWFLAG_CANBEWIPED:
792 Can_Be_Wiped = val;
793 break;
794 case TWFLAG_CANENCRYPTBACKUP:
795 Can_Encrypt_Backup = val;
796 break;
797 case TWFLAG_DEFAULTS:
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600798 case TWFLAG_WAIT:
799 case TWFLAG_VERIFY:
800 case TWFLAG_CHECK:
801 case TWFLAG_NOTRIM:
802 case TWFLAG_VOLDMANAGED:
803 case TWFLAG_RESIZE:
Matt Mower2416a502016-04-12 19:54:46 -0500804 // Do nothing
805 break;
806 case TWFLAG_DISPLAY:
807 Display_Name = str;
808 break;
809 case TWFLAG_ENCRYPTABLE:
810 case TWFLAG_FORCEENCRYPT:
811 Crypto_Key_Location = str;
812 break;
813 case TWFLAG_FLASHIMG:
814 Can_Flash_Img = val;
815 break;
816 case TWFLAG_FSFLAGS:
Matt Mower4ab42b12016-04-21 13:52:18 -0500817 Process_FS_Flags(str);
Matt Mower2416a502016-04-12 19:54:46 -0500818 break;
819 case TWFLAG_IGNOREBLKID:
820 Ignore_Blkid = val;
821 break;
822 case TWFLAG_LENGTH:
823 Length = atoi(str);
824 break;
825 case TWFLAG_MOUNTTODECRYPT:
826 Mount_To_Decrypt = val;
827 break;
828 case TWFLAG_REMOVABLE:
829 Removable = val;
830 break;
831 case TWFLAG_RETAINLAYOUTVERSION:
832 Retain_Layout_Version = val;
833 break;
834 case TWFLAG_SETTINGSSTORAGE:
835 Is_Settings_Storage = val;
836 if (Is_Settings_Storage)
837 Is_Storage = true;
838 break;
839 case TWFLAG_STORAGE:
840 Is_Storage = val;
841 break;
842 case TWFLAG_STORAGENAME:
843 Storage_Name = str;
844 break;
845 case TWFLAG_SUBPARTITIONOF:
846 Is_SubPartition = true;
847 SubPartition_Of = str;
848 break;
849 case TWFLAG_SYMLINK:
850 Symlink_Path = str;
851 break;
852 case TWFLAG_USERDATAENCRYPTBACKUP:
853 Use_Userdata_Encryption = val;
854 if (Use_Userdata_Encryption)
855 Can_Encrypt_Backup = true;
856 break;
857 case TWFLAG_USERMRF:
858 Use_Rm_Rf = val;
859 break;
860 case TWFLAG_WIPEDURINGFACTORYRESET:
861 Wipe_During_Factory_Reset = val;
862 if (Wipe_During_Factory_Reset) {
863 Can_Be_Wiped = true;
864 Wipe_Available_in_GUI = true;
865 }
866 break;
867 case TWFLAG_WIPEINGUI:
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600868 case TWFLAG_FORMATTABLE:
Matt Mower2416a502016-04-12 19:54:46 -0500869 Wipe_Available_in_GUI = val;
870 if (Wipe_Available_in_GUI)
871 Can_Be_Wiped = true;
872 break;
Ethan Yonker1b190162016-12-05 15:25:19 -0600873 case TWFLAG_SLOTSELECT:
874 SlotSelect = true;
875 break;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600876 case TWFLAG_ALTDEVICE:
877 Alternate_Block_Device = str;
878 break;
Matt Mower2416a502016-04-12 19:54:46 -0500879 default:
880 // Should not get here
881 LOGINFO("Flag identified for processing, but later unmatched: %i\n", flag);
882 break;
883 }
884}
Dees_Troy51127312012-09-08 13:08:49 -0400885
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600886void TWPartition::Process_TW_Flags(char *flags, bool Display_Error, int fstab_ver) {
Matt Mower2416a502016-04-12 19:54:46 -0500887 char separator[2] = {'\n', 0};
888 char *ptr, *savep;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600889 char source_separator = ';';
890
891 if (fstab_ver == 2)
892 source_separator = ',';
Matt Mower2416a502016-04-12 19:54:46 -0500893
894 // Semicolons within double-quotes are not forbidden, so replace
895 // only the semicolons intended as separators with '\n' for strtok
896 for (unsigned i = 0, skip = 0; i < strlen(flags); i++) {
897 if (flags[i] == '\"')
Dees_Troya13d74f2013-03-24 08:54:55 -0500898 skip = !skip;
Ethan Yonker6e8c27a2016-12-22 17:55:57 -0600899 if (!skip && flags[i] == source_separator)
Matt Mower2416a502016-04-12 19:54:46 -0500900 flags[i] = separator[0];
Dees_Troy51127312012-09-08 13:08:49 -0400901 }
902
Matt Mower2416a502016-04-12 19:54:46 -0500903 // Avoid issues with potentially nested strtok by using strtok_r
904 ptr = strtok_r(flags, separator, &savep);
905 while (ptr) {
906 int ptr_len = strlen(ptr);
907 const struct flag_list* tw_flag = tw_flags;
Hashcode62bd9e02013-11-19 21:59:42 -0800908
Matt Mower2416a502016-04-12 19:54:46 -0500909 for (; tw_flag->name; tw_flag++) {
910 int flag_len = strlen(tw_flag->name);
911
912 if (strncmp(ptr, tw_flag->name, flag_len) == 0) {
913 bool flag_val = false;
914
915 if (ptr_len > flag_len && (tw_flag->name)[flag_len-1] != '='
916 && ptr[flag_len] != '=') {
917 // Handle flags with same starting string
918 // (e.g. backup and backupname)
919 continue;
920 } else if (ptr_len > flag_len && ptr[flag_len] == '=') {
921 // Handle flags with dual format: Part 1
922 // (e.g. backup and backup=y. backup=y handled here)
923 ptr += flag_len + 1;
924 TWFunc::Strip_Quotes(ptr);
925 // Skip flags with empty argument
926 // (e.g. backup=)
927 if (strlen(ptr) == 0) {
928 LOGINFO("Flag missing argument or should not include '=': %s=\n", tw_flag->name);
929 break;
930 }
931 flag_val = strchr("yY1", *ptr) != NULL;
932 } else if (ptr_len == flag_len
933 && (tw_flag->name)[flag_len-1] == '=') {
934 // Skip flags missing argument after =
935 // (e.g. backupname=)
936 LOGINFO("Flag missing argument: %s\n", tw_flag->name);
937 break;
938 } else if (ptr_len > flag_len
939 && (tw_flag->name)[flag_len-1] == '=') {
940 // Handle arguments to flags
941 // (e.g. backupname="My Stuff")
942 ptr += flag_len;
943 TWFunc::Strip_Quotes(ptr);
944 // Skip flags with empty argument
945 // (e.g. backupname="")
946 if (strlen(ptr) == 0) {
947 LOGINFO("Flag missing argument: %s\n", tw_flag->name);
948 break;
949 }
950 } else if (ptr_len == flag_len) {
951 // Handle flags with dual format: Part 2
952 // (e.g. backup and backup=y. backup handled here)
953 flag_val = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600954 } else {
Matt Mower2416a502016-04-12 19:54:46 -0500955 LOGINFO("Flag matched, but could not be processed: %s\n", ptr);
956 break;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600957 }
Matt Mower2416a502016-04-12 19:54:46 -0500958
959 Apply_TW_Flag(tw_flag->flag, ptr, flag_val);
960 break;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600961 }
Matt Mower2416a502016-04-12 19:54:46 -0500962 }
963 if (tw_flag->name == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400964 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000965 LOGERR("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400966 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000967 LOGINFO("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400968 }
Matt Mower2416a502016-04-12 19:54:46 -0500969 ptr = strtok_r(NULL, separator, &savep);
Dees_Troy51127312012-09-08 13:08:49 -0400970 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400971}
972
Dees_Troy5bf43922012-09-07 16:07:55 -0400973bool TWPartition::Is_File_System(string File_System) {
974 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400975 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400976 File_System == "ext4" ||
977 File_System == "vfat" ||
978 File_System == "ntfs" ||
979 File_System == "yaffs2" ||
bigbiff bigbiff3e146522012-11-14 14:32:59 -0500980 File_System == "exfat" ||
Dees_Troye5017042013-08-29 16:38:55 +0000981 File_System == "f2fs" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400982 File_System == "auto")
983 return true;
984 else
985 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400986}
987
Dees_Troy5bf43922012-09-07 16:07:55 -0400988bool TWPartition::Is_Image(string File_System) {
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400989 if (File_System == "emmc" || File_System == "mtd" || File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400990 return true;
991 else
992 return false;
993}
994
Dees_Troy51127312012-09-08 13:08:49 -0400995bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Ethan Yonker93ac7a02016-11-07 22:05:58 -0600996 if (TWFunc::Get_D_Type_From_Stat(Path) != S_IFDIR)
997 unlink(Path.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400998 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400999 if (mkdir(Path.c_str(), 0777) == -1) {
1000 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001001 gui_msg(Msg(msg::kError, "create_folder_strerr=Can not create '{1}' folder ({2}).")(Path)(strerror(errno)));
Dees_Troy51127312012-09-08 13:08:49 -04001002 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001003 LOGINFO("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001004 return false;
1005 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001006 LOGINFO("Created '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001007 return true;
1008 }
1009 }
1010 return true;
1011}
1012
Dees_Troy5bf43922012-09-07 16:07:55 -04001013void TWPartition::Setup_File_System(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001014 Can_Be_Mounted = true;
1015 Can_Be_Wiped = true;
1016
Dees_Troy5bf43922012-09-07 16:07:55 -04001017 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -04001018 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -04001019 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
1020 Backup_Name = Display_Name;
bigbiffce8f83c2015-12-12 18:30:21 -05001021 Backup_Method = BM_FILES;
Dees_Troy5bf43922012-09-07 16:07:55 -04001022}
1023
Ethan Yonker1b190162016-12-05 15:25:19 -06001024void TWPartition::Setup_Image() {
Dees_Troy5bf43922012-09-07 16:07:55 -04001025 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
1026 Backup_Name = Display_Name;
Gary Peck82599a82012-11-21 16:23:12 -08001027 if (Current_File_System == "emmc")
bigbiffce8f83c2015-12-12 18:30:21 -05001028 Backup_Method = BM_DD;
Gary Peck82599a82012-11-21 16:23:12 -08001029 else if (Current_File_System == "mtd" || Current_File_System == "bml")
bigbiffce8f83c2015-12-12 18:30:21 -05001030 Backup_Method = BM_FLASH_UTILS;
Dees_Troy5bf43922012-09-07 16:07:55 -04001031 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001032 LOGINFO("Unhandled file system '%s' on image '%s'\n", Current_File_System.c_str(), Display_Name.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -04001033}
1034
Dees_Troye58d5262012-09-21 12:27:57 -04001035void TWPartition::Setup_AndSec(void) {
Dees_Troya13d74f2013-03-24 08:54:55 -05001036 Backup_Display_Name = "Android Secure";
Dees_Troye58d5262012-09-21 12:27:57 -04001037 Backup_Name = "and-sec";
Dees_Troya13d74f2013-03-24 08:54:55 -05001038 Can_Be_Backed_Up = true;
Dees_Troye58d5262012-09-21 12:27:57 -04001039 Has_Android_Secure = true;
1040 Symlink_Path = Mount_Point + "/.android_secure";
1041 Symlink_Mount_Point = "/and-sec";
1042 Backup_Path = Symlink_Mount_Point;
1043 Make_Dir("/and-sec", true);
1044 Recreate_AndSec_Folder();
Kjell Braden3126a112016-06-19 16:58:15 +00001045 Mount_Storage_Retry(true);
Dees_Troye58d5262012-09-21 12:27:57 -04001046}
1047
that9e0593e2014-10-08 00:01:24 +02001048void TWPartition::Setup_Data_Media() {
Ethan Yonker6277c792014-09-15 14:54:30 -05001049 LOGINFO("Setting up '%s' as data/media emulated storage.\n", Mount_Point.c_str());
Ethan Yonker66a19492015-12-10 10:19:45 -06001050 if (Storage_Name.empty() || Storage_Name == "Data")
1051 Storage_Name = "Internal Storage";
Ethan Yonker6277c792014-09-15 14:54:30 -05001052 Has_Data_Media = true;
1053 Is_Storage = true;
Ethan Yonker66a19492015-12-10 10:19:45 -06001054 Storage_Path = Mount_Point + "/media";
Ethan Yonker6277c792014-09-15 14:54:30 -05001055 Symlink_Path = Storage_Path;
Ethan Yonker66a19492015-12-10 10:19:45 -06001056 if (Mount_Point == "/data") {
1057 Is_Settings_Storage = true;
1058 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
1059 Make_Dir("/emmc", false);
1060 Symlink_Mount_Point = "/emmc";
1061 } else {
1062 Make_Dir("/sdcard", false);
1063 Symlink_Mount_Point = "/sdcard";
1064 }
1065 if (Mount(false) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
1066 Storage_Path = Mount_Point + "/media/0";
1067 Symlink_Path = Storage_Path;
1068 DataManager::SetValue(TW_INTERNAL_PATH, Mount_Point + "/media/0");
1069 UnMount(true);
1070 }
1071 DataManager::SetValue("tw_has_internal", 1);
1072 DataManager::SetValue("tw_has_data_media", 1);
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001073 backup_exclusions.add_absolute_dir("/data/data/com.google.android.music/files");
Ethan Yonker6355b562017-05-01 09:42:17 -05001074 wipe_exclusions.add_absolute_dir(Mount_Point + "/misc/vold"); // adopted storage keys
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001075 ExcludeAll(Mount_Point + "/.layout_version");
1076 ExcludeAll(Mount_Point + "/system/storage.xml");
Ethan Yonker6277c792014-09-15 14:54:30 -05001077 } else {
Ethan Yonker66a19492015-12-10 10:19:45 -06001078 if (Mount(true) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
1079 Storage_Path = Mount_Point + "/media/0";
1080 Symlink_Path = Storage_Path;
1081 UnMount(true);
1082 }
Ethan Yonker6277c792014-09-15 14:54:30 -05001083 }
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001084 ExcludeAll(Mount_Point + "/media");
Ethan Yonker6277c792014-09-15 14:54:30 -05001085}
1086
Dees_Troy5bf43922012-09-07 16:07:55 -04001087void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
Ethan Yonker6e8c27a2016-12-22 17:55:57 -06001088 char device[PATH_MAX], realDevice[PATH_MAX];
Dees_Troy5bf43922012-09-07 16:07:55 -04001089
1090 strcpy(device, Block.c_str());
1091 memset(realDevice, 0, sizeof(realDevice));
1092 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
1093 {
1094 strcpy(device, realDevice);
1095 memset(realDevice, 0, sizeof(realDevice));
1096 }
1097
1098 if (device[0] != '/') {
1099 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001100 LOGERR("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001101 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001102 LOGINFO("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001103 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001104 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -04001105 Block = device;
1106 return;
1107 }
1108}
1109
Kjell Braden3126a112016-06-19 16:58:15 +00001110bool TWPartition::Mount_Storage_Retry(bool Display_Error) {
Dees_Troy8e337f32012-10-13 22:07:49 -04001111 // On some devices, storage doesn't want to mount right away, retry and sleep
Kjell Braden3126a112016-06-19 16:58:15 +00001112 if (!Mount(Display_Error)) {
Dees_Troy8e337f32012-10-13 22:07:49 -04001113 int retry_count = 5;
1114 while (retry_count > 0 && !Mount(false)) {
1115 usleep(500000);
1116 retry_count--;
1117 }
Kjell Braden3126a112016-06-19 16:58:15 +00001118 return Mount(Display_Error);
Dees_Troy8e337f32012-10-13 22:07:49 -04001119 }
Kjell Braden3126a112016-06-19 16:58:15 +00001120 return true;
Dees_Troy8e337f32012-10-13 22:07:49 -04001121}
1122
Dees_Troy38bd7602012-09-14 13:33:53 -04001123bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
1124 FILE *fp = NULL;
1125 char line[255];
1126
1127 fp = fopen("/proc/mtd", "rt");
1128 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001129 LOGERR("Device does not support /proc/mtd\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001130 return false;
1131 }
1132
1133 while (fgets(line, sizeof(line), fp) != NULL)
1134 {
1135 char device[32], label[32];
1136 unsigned long size = 0;
Dees_Troy38bd7602012-09-14 13:33:53 -04001137 int deviceId;
1138
1139 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
1140
1141 // Skip header and blank lines
1142 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
1143 continue;
1144
1145 // Strip off the trailing " from the label
1146 label[strlen(label)-1] = '\0';
1147
1148 if (strcmp(label, MTD_Name.c_str()) == 0) {
1149 // We found our device
1150 // Strip off the trailing : from the device
1151 device[strlen(device)-1] = '\0';
1152 if (sscanf(device,"mtd%d", &deviceId) == 1) {
1153 sprintf(device, "/dev/block/mtdblock%d", deviceId);
1154 Primary_Block_Device = device;
Dees_Troy76543db2013-06-19 16:24:30 +00001155 fclose(fp);
1156 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04001157 }
1158 }
1159 }
1160 fclose(fp);
1161
1162 return false;
1163}
1164
Dees_Troy51127312012-09-08 13:08:49 -04001165bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
1166 struct statfs st;
1167 string Local_Path = Mount_Point + "/.";
1168
1169 if (!Mount(Display_Error))
1170 return false;
1171
1172 if (statfs(Local_Path.c_str(), &st) != 0) {
1173 if (!Removable) {
1174 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001175 LOGERR("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001176 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001177 LOGINFO("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001178 }
1179 return false;
1180 }
1181 Size = (st.f_blocks * st.f_bsize);
1182 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
1183 Free = (st.f_bfree * st.f_bsize);
1184 Backup_Size = Used;
1185 return true;
1186}
1187
1188bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001189 FILE* fp;
1190 char command[255], line[512];
1191 int include_block = 1;
1192 unsigned int min_len;
1193
1194 if (!Mount(Display_Error))
1195 return false;
1196
Dees_Troy38bd7602012-09-14 13:33:53 -04001197 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -04001198 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001199 TWFunc::Exec_Cmd(command);
Dees_Troy51127312012-09-08 13:08:49 -04001200 fp = fopen("/tmp/dfoutput.txt", "rt");
1201 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001202 LOGINFO("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001203 return false;
Dees_Troy51127312012-09-08 13:08:49 -04001204 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001205
1206 while (fgets(line, sizeof(line), fp) != NULL)
1207 {
1208 unsigned long blocks, used, available;
1209 char device[64];
1210 char tmpString[64];
1211
1212 if (strncmp(line, "Filesystem", 10) == 0)
1213 continue;
1214 if (strlen(line) < min_len) {
1215 include_block = 0;
1216 continue;
1217 }
1218 if (include_block) {
1219 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
1220 } else {
1221 // The device block string is so long that the df information is on the next line
1222 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -04001223 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001224 while (tmpString[space_count] == 32)
1225 space_count++;
1226 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
1227 }
1228
1229 // Adjust block size to byte size
1230 Size = blocks * 1024ULL;
1231 Used = used * 1024ULL;
1232 Free = available * 1024ULL;
1233 Backup_Size = Used;
1234 }
1235 fclose(fp);
1236 return true;
1237}
1238
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001239unsigned long long TWPartition::IOCTL_Get_Block_Size() {
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001240 Find_Actual_Block_Device();
Ethan Yonker483e9f42016-01-11 22:21:18 -06001241
1242 return TWFunc::IOCTL_Get_Block_Size(Actual_Block_Device.c_str());
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001243}
1244
Dees_Troy5bf43922012-09-07 16:07:55 -04001245bool TWPartition::Find_Partition_Size(void) {
1246 FILE* fp;
1247 char line[512];
1248 string tmpdevice;
1249
igoriok87e3d932013-01-31 21:03:53 +02001250 fp = fopen("/proc/dumchar_info", "rt");
1251 if (fp != NULL) {
1252 while (fgets(line, sizeof(line), fp) != NULL)
1253 {
1254 char label[32], device[32];
1255 unsigned long size = 0;
1256
thatd43bf2d2014-09-21 23:13:02 +02001257 sscanf(line, "%s %lx %*x %*u %s", label, &size, device);
igoriok87e3d932013-01-31 21:03:53 +02001258
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001259 // Skip header, annotation and blank lines
igoriok87e3d932013-01-31 21:03:53 +02001260 if ((strncmp(device, "/dev/", 5) != 0) || (strlen(line) < 8))
1261 continue;
1262
1263 tmpdevice = "/dev/";
1264 tmpdevice += label;
1265 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
1266 Size = size;
1267 fclose(fp);
1268 return true;
1269 }
1270 }
1271 }
1272
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001273 unsigned long long ioctl_size = IOCTL_Get_Block_Size();
1274 if (ioctl_size) {
1275 Size = ioctl_size;
1276 return true;
1277 }
1278
Dees_Troy5bf43922012-09-07 16:07:55 -04001279 // In this case, we'll first get the partitions we care about (with labels)
1280 fp = fopen("/proc/partitions", "rt");
1281 if (fp == NULL)
1282 return false;
1283
1284 while (fgets(line, sizeof(line), fp) != NULL)
1285 {
1286 unsigned long major, minor, blocks;
1287 char device[512];
Dees_Troy5bf43922012-09-07 16:07:55 -04001288
Dees_Troy63c8df72012-09-10 14:02:05 -04001289 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -04001290 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
1291
1292 tmpdevice = "/dev/block/";
1293 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -04001294 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001295 // Adjust block size to byte size
1296 Size = blocks * 1024ULL;
1297 fclose(fp);
1298 return true;
1299 }
1300 }
1301 fclose(fp);
1302 return false;
1303}
1304
Dees_Troy5bf43922012-09-07 16:07:55 -04001305bool TWPartition::Is_Mounted(void) {
1306 if (!Can_Be_Mounted)
1307 return false;
1308
1309 struct stat st1, st2;
1310 string test_path;
1311
1312 // Check to see if the mount point directory exists
1313 test_path = Mount_Point + "/.";
1314 if (stat(test_path.c_str(), &st1) != 0) return false;
1315
1316 // Check to see if the directory above the mount point exists
1317 test_path = Mount_Point + "/../.";
1318 if (stat(test_path.c_str(), &st2) != 0) return false;
1319
1320 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
1321 int ret = (st1.st_dev != st2.st_dev) ? true : false;
1322
1323 return ret;
1324}
1325
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05001326bool TWPartition::Is_File_System_Writable(void) {
1327 if (!Is_File_System(Current_File_System) || !Is_Mounted())
1328 return false;
1329
1330 string test_path = Mount_Point + "/.";
1331 return (access(test_path.c_str(), W_OK) == 0);
1332}
1333
Dees_Troy5bf43922012-09-07 16:07:55 -04001334bool TWPartition::Mount(bool Display_Error) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001335 int exfat_mounted = 0;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001336 unsigned long flags = Mount_Flags;
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001337
Dees_Troy5bf43922012-09-07 16:07:55 -04001338 if (Is_Mounted()) {
1339 return true;
1340 } else if (!Can_Be_Mounted) {
1341 return false;
1342 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001343
1344 Find_Actual_Block_Device();
1345
1346 // Check the current file system before mounting
1347 Check_FS_Type();
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001348 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/exfat-fuse")) {
Dees_Troye34c1332013-02-06 19:13:00 +00001349 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 +00001350 LOGINFO("cmd: %s\n", cmd.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001351 string result;
1352 if (TWFunc::Exec_Cmd(cmd, result) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001353 LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001354 Current_File_System = "vfat";
1355 } else {
1356#ifdef TW_NO_EXFAT_FUSE
1357 UnMount(false);
1358 // We'll let the kernel handle it but using exfat-fuse to detect if the file system is actually exfat
1359 // Some kernels let us mount vfat as exfat which doesn't work out too well
1360#else
1361 exfat_mounted = 1;
1362#endif
1363 }
1364 }
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001365
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001366 if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfs-3g") || TWFunc::Path_Exists("/sbin/mount.ntfs"))) {
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001367 string cmd;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001368 string Ntfsmount_Binary = "";
1369
1370 if (TWFunc::Path_Exists("/sbin/ntfs-3g"))
1371 Ntfsmount_Binary = "ntfs-3g";
1372 else if (TWFunc::Path_Exists("/sbin/mount.ntfs"))
1373 Ntfsmount_Binary = "mount.ntfs";
1374
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001375 if (Mount_Read_Only)
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001376 cmd = "/sbin/" + Ntfsmount_Binary + " -o ro " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001377 else
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001378 cmd = "/sbin/" + Ntfsmount_Binary + " " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001379 LOGINFO("cmd: '%s'\n", cmd.c_str());
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001380
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001381 if (TWFunc::Exec_Cmd(cmd) == 0) {
1382 return true;
1383 } else {
1384 LOGINFO("ntfs-3g failed to mount, trying regular mount method.\n");
1385 }
1386 }
1387
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001388 if (Mount_Read_Only)
1389 flags |= MS_RDONLY;
1390
Dees_Troy22042032012-12-18 21:23:08 +00001391 if (Fstab_File_System == "yaffs2") {
1392 // mount an MTD partition as a YAFFS2 filesystem.
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001393 flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
1394 if (Mount_Read_Only)
1395 flags |= MS_RDONLY;
Dees_Troy76543db2013-06-19 16:24:30 +00001396 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
1397 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
1398 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001399 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001400 else
1401 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1402 return false;
1403 } else {
1404 LOGINFO("Mounted '%s' (MTD) as RO\n", Mount_Point.c_str());
1405 return true;
1406 }
1407 } else {
1408 struct stat st;
1409 string test_path = Mount_Point;
1410 if (stat(test_path.c_str(), &st) < 0) {
1411 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001412 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001413 else
1414 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1415 return false;
1416 }
1417 mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
1418 if (new_mode != st.st_mode) {
1419 LOGINFO("Fixing execute permissions for %s\n", Mount_Point.c_str());
1420 if (chmod(Mount_Point.c_str(), new_mode) < 0) {
1421 if (Display_Error)
1422 LOGERR("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1423 else
1424 LOGINFO("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1425 return false;
1426 }
1427 }
Dees_Troy22042032012-12-18 21:23:08 +00001428 return true;
Dees_Troy76543db2013-06-19 16:24:30 +00001429 }
thatc7572eb2015-03-31 18:55:30 +02001430 }
1431
1432 string mount_fs = Current_File_System;
1433 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sys/module/texfat"))
1434 mount_fs = "texfat";
1435
1436 if (!exfat_mounted &&
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001437 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, Mount_Options.c_str()) != 0 &&
1438 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, NULL) != 0) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001439#ifdef TW_NO_EXFAT_FUSE
1440 if (Current_File_System == "exfat") {
Dees_Troy2673cec2013-04-02 20:22:16 +00001441 LOGINFO("Mounting exfat failed, trying vfat...\n");
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001442 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), "vfat", 0, NULL) != 0) {
Dees_Troy85f44ed2013-01-09 18:42:36 +00001443 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001444 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy85f44ed2013-01-09 18:42:36 +00001445 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001446 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001447 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 +00001448 return false;
Dees_Troy85f44ed2013-01-09 18:42:36 +00001449 }
Dees_Troyb05ddee2013-01-28 20:24:50 +00001450 } else {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001451#endif
bigbiff bigbiff26774a02014-03-29 18:22:00 -04001452 if (!Removable && Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001453 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001454 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001455 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
1456 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 +00001457 return false;
1458#ifdef TW_NO_EXFAT_FUSE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001459 }
1460#endif
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001461 }
Ethan Yonker253368a2014-11-25 15:00:52 -06001462
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001463 if (Removable)
1464 Update_Size(Display_Error);
1465
xiaolu9416f4f2015-06-04 08:22:23 +08001466 if (!Symlink_Mount_Point.empty() && TWFunc::Path_Exists(Symlink_Path)) {
codelover2a3d4ce2015-03-14 20:26:49 +08001467 string Command = "mount -o bind '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
Vojtech Bocek05534202013-09-11 08:11:56 +02001468 TWFunc::Exec_Cmd(Command);
Dees_Troy5bf43922012-09-07 16:07:55 -04001469 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001470 return true;
1471}
1472
1473bool TWPartition::UnMount(bool Display_Error) {
1474 if (Is_Mounted()) {
1475 int never_unmount_system;
1476
1477 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
1478 if (never_unmount_system == 1 && Mount_Point == "/system")
1479 return true; // Never unmount system if you're not supposed to unmount it
1480
Matt Mowera8e6d832017-02-14 20:20:59 -06001481 if (Is_Storage && MTP_Storage_ID > 0)
Ethan Yonker726a0202014-12-16 20:01:38 -06001482 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001483
Dees_Troy38bd7602012-09-14 13:33:53 -04001484 if (!Symlink_Mount_Point.empty())
1485 umount(Symlink_Mount_Point.c_str());
1486
Dees_Troyb05ddee2013-01-28 20:24:50 +00001487 umount(Mount_Point.c_str());
1488 if (Is_Mounted()) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001489 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001490 gui_msg(Msg(msg::kError, "fail_unmount=Failed to unmount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy5bf43922012-09-07 16:07:55 -04001491 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001492 LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001493 return false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001494 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -04001495 return true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001496 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001497 } else {
1498 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001499 }
1500}
1501
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05001502bool TWPartition::ReMount(bool Display_Error) {
1503 if (UnMount(Display_Error))
1504 return Mount(Display_Error);
1505 return false;
1506}
1507
1508bool TWPartition::ReMount_RW(bool Display_Error) {
1509 // No need to remount if already mounted rw
1510 if (Is_File_System_Writable())
1511 return true;
1512
1513 bool ro = Mount_Read_Only;
1514 int flags = Mount_Flags;
1515
1516 Mount_Read_Only = false;
1517 Mount_Flags &= ~MS_RDONLY;
1518
1519 bool ret = ReMount(Display_Error);
1520
1521 Mount_Read_Only = ro;
1522 Mount_Flags = flags;
1523
1524 return ret;
1525}
1526
Gary Peck43acadf2012-11-21 21:19:01 -08001527bool TWPartition::Wipe(string New_File_System) {
Ethan Yonker726a0202014-12-16 20:01:38 -06001528 bool wiped = false, update_crypt = false, recreate_media = true;
Dees_Troy16c2b312013-01-15 16:51:18 +00001529 int check;
1530 string Layout_Filename = Mount_Point + "/.layout_version";
1531
Dees_Troy38bd7602012-09-14 13:33:53 -04001532 if (!Can_Be_Wiped) {
Matt Mower3c366972015-12-25 19:28:31 -06001533 gui_msg(Msg(msg::kError, "cannot_wipe=Partition {1} cannot be wiped.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001534 return false;
1535 }
1536
Dees_Troyc51f1f92012-09-20 15:32:13 -04001537 if (Mount_Point == "/cache")
Dees_Troy2673cec2013-04-02 20:22:16 +00001538 Log_Offset = 0;
Dees_Troyc51f1f92012-09-20 15:32:13 -04001539
Dees_Troy16c2b312013-01-15 16:51:18 +00001540 if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
1541 TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
1542 else
1543 unlink("/.layout_version");
Dees_Troy38bd7602012-09-14 13:33:53 -04001544
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001545 if (Has_Data_Media && Current_File_System == New_File_System) {
Dees_Troy16c2b312013-01-15 16:51:18 +00001546 wiped = Wipe_Data_Without_Wiping_Media();
Ethan Yonker5eac2222014-06-11 12:22:55 -05001547 recreate_media = false;
Dees_Troy16c2b312013-01-15 16:51:18 +00001548 } else {
Dees_Troy16c2b312013-01-15 16:51:18 +00001549 DataManager::GetValue(TW_RM_RF_VAR, check);
1550
Hashcodedabfd492013-08-29 22:45:30 -07001551 if (check || Use_Rm_Rf)
Dees_Troy16c2b312013-01-15 16:51:18 +00001552 wiped = Wipe_RMRF();
1553 else if (New_File_System == "ext4")
1554 wiped = Wipe_EXT4();
1555 else if (New_File_System == "ext2" || New_File_System == "ext3")
1556 wiped = Wipe_EXT23(New_File_System);
1557 else if (New_File_System == "vfat")
1558 wiped = Wipe_FAT();
1559 else if (New_File_System == "exfat")
1560 wiped = Wipe_EXFAT();
1561 else if (New_File_System == "yaffs2")
1562 wiped = Wipe_MTD();
Dees_Troye5017042013-08-29 16:38:55 +00001563 else if (New_File_System == "f2fs")
1564 wiped = Wipe_F2FS();
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001565 else if (New_File_System == "ntfs")
1566 wiped = Wipe_NTFS();
Dees_Troy16c2b312013-01-15 16:51:18 +00001567 else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001568 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 +00001569 unlink("/.layout_version");
1570 return false;
1571 }
1572 update_crypt = wiped;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001573 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001574
Gary Pecke8bc5d72012-12-21 06:45:25 -08001575 if (wiped) {
Dees_Troy1c1ac442013-01-17 21:42:14 +00001576 if (Mount_Point == "/cache")
1577 DataManager::Output_Version();
1578
Dees_Troy16c2b312013-01-15 16:51:18 +00001579 if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
1580 TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
1581
1582 if (update_crypt) {
1583 Setup_File_System(false);
1584 if (Is_Encrypted && !Is_Decrypted) {
1585 // just wiped an encrypted partition back to its unencrypted state
1586 Is_Encrypted = false;
1587 Is_Decrypted = false;
1588 Decrypted_Block_Device = "";
1589 if (Mount_Point == "/data") {
1590 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1591 DataManager::SetValue(TW_IS_DECRYPTED, 0);
1592 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001593 }
1594 }
Ethan Yonker5eac2222014-06-11 12:22:55 -05001595
Ethan Yonker66a19492015-12-10 10:19:45 -06001596 if (Has_Data_Media && recreate_media) {
Ethan Yonker5eac2222014-06-11 12:22:55 -05001597 Recreate_Media_Folder();
1598 }
Matt Mower209c9632016-01-20 12:08:35 -06001599 if (Is_Storage && Mount(false))
1600 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Gary Pecke8bc5d72012-12-21 06:45:25 -08001601 }
Matt Mower209c9632016-01-20 12:08:35 -06001602
Gary Pecke8bc5d72012-12-21 06:45:25 -08001603 return wiped;
Dees_Troy51a0e822012-09-05 15:24:24 -04001604}
1605
Gary Peck43acadf2012-11-21 21:19:01 -08001606bool TWPartition::Wipe() {
Gary Peck82599a82012-11-21 16:23:12 -08001607 if (Is_File_System(Current_File_System))
1608 return Wipe(Current_File_System);
1609 else
1610 return Wipe(Fstab_File_System);
Gary Peck43acadf2012-11-21 21:19:01 -08001611}
1612
Dees_Troye58d5262012-09-21 12:27:57 -04001613bool TWPartition::Wipe_AndSec(void) {
1614 if (!Has_Android_Secure)
1615 return false;
1616
Dees_Troye58d5262012-09-21 12:27:57 -04001617 if (!Mount(true))
1618 return false;
1619
Ethan Yonker74db1572015-10-28 12:44:49 -05001620 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001621 TWFunc::removeDir(Mount_Point + "/.android_secure/", true);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001622 return true;
Dees_Troye58d5262012-09-21 12:27:57 -04001623}
1624
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001625bool TWPartition::Can_Repair() {
Ethan Yonkera2719152015-05-28 09:44:41 -05001626 if (Mount_Read_Only)
1627 return false;
Matt Mower18794c82015-11-11 16:22:45 -06001628 if (Current_File_System == "vfat" && TWFunc::Path_Exists("/sbin/fsck.fat"))
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001629 return true;
1630 else if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/e2fsck"))
1631 return true;
1632 else if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/fsck.exfat"))
1633 return true;
1634 else if (Current_File_System == "f2fs" && TWFunc::Path_Exists("/sbin/fsck.f2fs"))
1635 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001636 else if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfsfix") || TWFunc::Path_Exists("/sbin/fsck.ntfs")))
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001637 return true;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001638 return false;
1639}
1640
1641bool TWPartition::Repair() {
1642 string command;
1643
1644 if (Current_File_System == "vfat") {
Matt Mower18794c82015-11-11 16:22:45 -06001645 if (!TWFunc::Path_Exists("/sbin/fsck.fat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001646 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001647 return false;
1648 }
1649 if (!UnMount(true))
1650 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001651 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001652 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06001653 command = "/sbin/fsck.fat -y " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001654 LOGINFO("Repair command: %s\n", command.c_str());
1655 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001656 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001657 return true;
1658 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001659 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001660 return false;
1661 }
1662 }
1663 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1664 if (!TWFunc::Path_Exists("/sbin/e2fsck")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001665 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001666 return false;
1667 }
1668 if (!UnMount(true))
1669 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001670 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001671 Find_Actual_Block_Device();
Ethan Yonkera2719152015-05-28 09:44:41 -05001672 command = "/sbin/e2fsck -fp " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001673 LOGINFO("Repair command: %s\n", command.c_str());
1674 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001675 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001676 return true;
1677 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001678 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001679 return false;
1680 }
1681 }
1682 if (Current_File_System == "exfat") {
1683 if (!TWFunc::Path_Exists("/sbin/fsck.exfat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001684 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001685 return false;
1686 }
1687 if (!UnMount(true))
1688 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001689 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001690 Find_Actual_Block_Device();
1691 command = "/sbin/fsck.exfat " + Actual_Block_Device;
1692 LOGINFO("Repair command: %s\n", command.c_str());
1693 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001694 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001695 return true;
1696 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001697 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001698 return false;
1699 }
1700 }
1701 if (Current_File_System == "f2fs") {
1702 if (!TWFunc::Path_Exists("/sbin/fsck.f2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001703 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001704 return false;
1705 }
1706 if (!UnMount(true))
1707 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001708 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001709 Find_Actual_Block_Device();
1710 command = "/sbin/fsck.f2fs " + Actual_Block_Device;
1711 LOGINFO("Repair command: %s\n", command.c_str());
1712 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001713 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001714 return true;
1715 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001716 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001717 return false;
1718 }
1719 }
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001720 if (Current_File_System == "ntfs") {
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001721 string Ntfsfix_Binary;
1722 if (TWFunc::Path_Exists("/sbin/ntfsfix"))
1723 Ntfsfix_Binary = "ntfsfix";
1724 else if (TWFunc::Path_Exists("/sbin/fsck.ntfs"))
1725 Ntfsfix_Binary = "fsck.ntfs";
1726 else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001727 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("ntfsfix"));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001728 return false;
1729 }
1730 if (!UnMount(true))
1731 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001732 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)(Ntfsfix_Binary));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001733 Find_Actual_Block_Device();
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001734 command = "/sbin/" + Ntfsfix_Binary + " " + Actual_Block_Device;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001735 LOGINFO("Repair command: %s\n", command.c_str());
1736 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001737 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001738 return true;
1739 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001740 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001741 return false;
1742 }
1743 }
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001744 return false;
1745}
1746
Ethan Yonkera2719152015-05-28 09:44:41 -05001747bool TWPartition::Can_Resize() {
1748 if (Mount_Read_Only)
1749 return false;
1750 if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/resize2fs"))
1751 return true;
1752 return false;
1753}
1754
1755bool TWPartition::Resize() {
1756 string command;
1757
1758 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1759 if (!Can_Repair()) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001760 LOGINFO("Cannot resize %s because %s cannot be repaired before resizing.\n", Display_Name.c_str(), Display_Name.c_str());
1761 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001762 return false;
1763 }
1764 if (!TWFunc::Path_Exists("/sbin/resize2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001765 LOGINFO("resize2fs does not exist! Cannot resize!\n");
1766 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001767 return false;
1768 }
1769 // Repair will unmount so no need to do it twice
Ethan Yonker74db1572015-10-28 12:44:49 -05001770 gui_msg(Msg("repair_resize=Repairing {1} before resizing.")( Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001771 if (!Repair())
1772 return false;
Ethan Yonker74db1572015-10-28 12:44:49 -05001773 gui_msg(Msg("resizing=Resizing {1} using {2}...")(Display_Name)("resize2fs"));
Ethan Yonkera2719152015-05-28 09:44:41 -05001774 Find_Actual_Block_Device();
1775 command = "/sbin/resize2fs " + Actual_Block_Device;
1776 if (Length != 0) {
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001777 unsigned long long Actual_Size = IOCTL_Get_Block_Size();
1778 if (Actual_Size == 0)
1779 return false;
Ethan Yonkera2719152015-05-28 09:44:41 -05001780
Ethan Yonkera2719152015-05-28 09:44:41 -05001781 unsigned long long Block_Count;
1782 if (Length < 0) {
1783 // Reduce overall size by this length
1784 Block_Count = (Actual_Size / 1024LLU) - ((unsigned long long)(Length * -1) / 1024LLU);
1785 } else {
1786 // This is the size, not a size reduction
1787 Block_Count = ((unsigned long long)(Length) / 1024LLU);
1788 }
1789 char temp[256];
1790 sprintf(temp, "%llu", Block_Count);
1791 command += " ";
1792 command += temp;
1793 command += "K";
1794 }
1795 LOGINFO("Resize command: %s\n", command.c_str());
1796 if (TWFunc::Exec_Cmd(command) == 0) {
1797 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001798 gui_msg("done=Done.");
Ethan Yonkera2719152015-05-28 09:44:41 -05001799 return true;
1800 } else {
1801 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001802 gui_msg(Msg(msg::kError, "unable_resize=Unable to resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001803 return false;
1804 }
1805 }
1806 return false;
1807}
1808
bigbiffce8f83c2015-12-12 18:30:21 -05001809bool TWPartition::Backup(PartitionSettings *part_settings, pid_t *tar_fork_pid) {
1810 if (Backup_Method == BM_FILES)
1811 return Backup_Tar(part_settings, tar_fork_pid);
1812 else if (Backup_Method == BM_DD)
1813 return Backup_Image(part_settings);
1814 else if (Backup_Method == BM_FLASH_UTILS)
1815 return Backup_Dump_Image(part_settings);
Dees_Troy2673cec2013-04-02 20:22:16 +00001816 LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001817 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001818}
1819
bigbiffce8f83c2015-12-12 18:30:21 -05001820bool TWPartition::Restore(PartitionSettings *part_settings) {
Matt Mower3c366972015-12-25 19:28:31 -06001821 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonkere080c1f2016-09-19 13:50:25 -05001822 LOGINFO("Restore filename is: %s/%s\n", part_settings->Backup_Folder.c_str(), Backup_FileName.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001823
bigbiffce8f83c2015-12-12 18:30:21 -05001824 string Restore_File_System = Get_Restore_File_System(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001825
1826 if (Is_File_System(Restore_File_System))
bigbiffce8f83c2015-12-12 18:30:21 -05001827 return Restore_Tar(part_settings);
1828 else if (Is_Image(Restore_File_System))
1829 return Restore_Image(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001830
1831 LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str());
1832 return false;
1833}
1834
bigbiffce8f83c2015-12-12 18:30:21 -05001835string TWPartition::Get_Restore_File_System(PartitionSettings *part_settings) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001836 size_t first_period, second_period;
1837 string Restore_File_System;
1838
Gary Peck43acadf2012-11-21 21:19:01 -08001839 // Parse backup filename to extract the file system before wiping
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05001840 first_period = Backup_FileName.find(".");
Gary Peck43acadf2012-11-21 21:19:01 -08001841 if (first_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001842 LOGERR("Unable to find file system (first period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001843 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001844 }
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05001845 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
Gary Peck43acadf2012-11-21 21:19:01 -08001846 second_period = Restore_File_System.find(".");
1847 if (second_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001848 LOGERR("Unable to find file system (second period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001849 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001850 }
1851 Restore_File_System.resize(second_period);
Matt Mowera0cd91d2016-12-30 18:21:42 -06001852 LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001853 return Restore_File_System;
Dees_Troy51a0e822012-09-05 15:24:24 -04001854}
1855
1856string TWPartition::Backup_Method_By_Name() {
bigbiffce8f83c2015-12-12 18:30:21 -05001857 if (Backup_Method == BM_NONE)
Dees_Troy38bd7602012-09-14 13:33:53 -04001858 return "none";
bigbiffce8f83c2015-12-12 18:30:21 -05001859 else if (Backup_Method == BM_FILES)
Dees_Troy38bd7602012-09-14 13:33:53 -04001860 return "files";
bigbiffce8f83c2015-12-12 18:30:21 -05001861 else if (Backup_Method == BM_DD)
Dees_Troy38bd7602012-09-14 13:33:53 -04001862 return "dd";
bigbiffce8f83c2015-12-12 18:30:21 -05001863 else if (Backup_Method == BM_FLASH_UTILS)
Dees_Troy38bd7602012-09-14 13:33:53 -04001864 return "flash_utils";
1865 else
1866 return "undefined";
1867 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -04001868}
1869
1870bool TWPartition::Decrypt(string Password) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001871 LOGINFO("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001872 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -04001873 return 1;
1874}
1875
1876bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001877 bool Save_Data_Media = Has_Data_Media;
1878
1879 if (!UnMount(true))
1880 return false;
1881
Dees_Troy38bd7602012-09-14 13:33:53 -04001882 Has_Data_Media = false;
Dees_Troy74fb2e92013-04-15 14:35:47 +00001883 Decrypted_Block_Device = "";
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001884#ifdef TW_INCLUDE_CRYPTO
Ethan Yonker1b190162016-12-05 15:25:19 -06001885 if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001886 if (!UnMount(true))
1887 return false;
Matt Mower2b18a532015-02-20 16:58:05 -06001888 if (delete_crypto_blk_dev((char*)("userdata")) != 0) {
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001889 LOGERR("Error deleting crypto block device, continuing anyway.\n");
1890 }
1891 }
1892#endif
Dees_Troy74fb2e92013-04-15 14:35:47 +00001893 Is_Decrypted = false;
1894 Is_Encrypted = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001895 Find_Actual_Block_Device();
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001896 if (Crypto_Key_Location == "footer") {
1897 int newlen, fd;
1898 if (Length != 0) {
1899 newlen = Length;
1900 if (newlen < 0)
1901 newlen = newlen * -1;
1902 } else {
1903 newlen = CRYPT_FOOTER_OFFSET;
1904 }
1905 if ((fd = open(Actual_Block_Device.c_str(), O_RDWR)) < 0) {
1906 gui_print_color("warning", "Unable to open '%s' to wipe crypto key\n", Actual_Block_Device.c_str());
1907 } else {
1908 unsigned int block_count;
1909 if ((ioctl(fd, BLKGETSIZE, &block_count)) == -1) {
1910 gui_print_color("warning", "Unable to get block size for wiping crypto footer.\n");
1911 } else {
1912 off64_t offset = ((off64_t)block_count * 512) - newlen;
1913 if (lseek64(fd, offset, SEEK_SET) == -1) {
1914 gui_print_color("warning", "Unable to lseek64 for wiping crypto footer.\n");
1915 } else {
1916 void* buffer = malloc(newlen);
1917 if (!buffer) {
1918 gui_print_color("warning", "Failed to malloc for wiping crypto footer.\n");
1919 } else {
1920 memset(buffer, 0, newlen);
1921 int ret = write(fd, buffer, newlen);
1922 if (ret != newlen) {
1923 gui_print_color("warning", "Failed to wipe crypto footer.\n");
1924 } else {
1925 LOGINFO("Successfully wiped crypto footer.\n");
1926 }
Matt Mower13a8f0b2015-09-26 15:40:03 -05001927 free(buffer);
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001928 }
1929 }
1930 }
1931 close(fd);
1932 }
1933 } else {
Ethan Yonkerc2dafbb2016-03-15 22:20:59 -05001934 if (TWFunc::IOCTL_Get_Block_Size(Crypto_Key_Location.c_str()) >= 16384LLU) {
1935 string Command = "dd of='" + Crypto_Key_Location + "' if=/dev/zero bs=16384 count=1";
1936 TWFunc::Exec_Cmd(Command);
1937 } else {
1938 LOGINFO("Crypto key location reports size < 16K so not wiping crypto footer.\n");
1939 }
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001940 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001941 if (Wipe(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001942 Has_Data_Media = Save_Data_Media;
1943 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
1944 Recreate_Media_Folder();
Ethan Yonker726a0202014-12-16 20:01:38 -06001945 if (Mount(false))
1946 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001947 }
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001948 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
Ethan Yonker83e82572014-04-04 10:59:28 -05001949#ifndef TW_OEM_BUILD
Ethan Yonker74db1572015-10-28 12:44:49 -05001950 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 -05001951#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001952 return true;
1953 } else {
1954 Has_Data_Media = Save_Data_Media;
Ethan Yonker74db1572015-10-28 12:44:49 -05001955 gui_err("format_data_err=Unable to format to remove encryption.");
Ethan Yonker726a0202014-12-16 20:01:38 -06001956 if (Has_Data_Media && Mount(false))
1957 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001958 return false;
1959 }
1960 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001961}
1962
1963void TWPartition::Check_FS_Type() {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001964 const char* type;
1965 blkid_probe pr;
Dees_Troy5bf43922012-09-07 16:07:55 -04001966
Dees_Troy68cab492012-12-12 19:29:35 +00001967 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd" || Fstab_File_System == "bml" || Ignore_Blkid)
1968 return; // Running blkid on some mtd devices causes a massive crash or needs to be skipped
Dees_Troy5bf43922012-09-07 16:07:55 -04001969
Dees_Troy38bd7602012-09-14 13:33:53 -04001970 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -04001971 if (!Is_Present)
1972 return;
Dees_Troy51127312012-09-08 13:08:49 -04001973
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001974 pr = blkid_new_probe_from_filename(Actual_Block_Device.c_str());
1975 if (blkid_do_fullprobe(pr)) {
1976 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001977 LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001978 return;
Dees_Troy5bf43922012-09-07 16:07:55 -04001979 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001980
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001981 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001982 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001983 LOGINFO("can't find filesystem on device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001984 return;
1985 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001986
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001987 Current_File_System = type;
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001988 blkid_free_probe(pr);
Ethan Yonker6e8c27a2016-12-22 17:55:57 -06001989 if (fs_flags.size() > 1) {
1990 std::vector<partition_fs_flags_struct>::iterator iter;
1991 std::vector<partition_fs_flags_struct>::iterator found = fs_flags.begin();
1992
1993 for (iter = fs_flags.begin(); iter != fs_flags.end(); iter++) {
1994 if (iter->File_System == Current_File_System) {
1995 found = iter;
1996 break;
1997 }
1998 }
1999 // If we don't find a match, we default the flags to the first set of flags that we received from the fstab
2000 if (Mount_Flags != found->Mount_Flags || Mount_Options != found->Mount_Options) {
2001 Mount_Flags = found->Mount_Flags;
2002 Mount_Options = found->Mount_Options;
2003 LOGINFO("Mount_Flags: %i, Mount_Options: %s\n", Mount_Flags, Mount_Options.c_str());
2004 }
2005 }
Dees_Troy51a0e822012-09-05 15:24:24 -04002006}
2007
Gary Peck43acadf2012-11-21 21:19:01 -08002008bool TWPartition::Wipe_EXT23(string File_System) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002009 if (!UnMount(true))
2010 return false;
2011
Dees_Troy43d8b002012-09-17 16:00:01 -04002012 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02002013 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04002014
Greg Wallace4b44fef2015-12-29 15:33:24 -05002015 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mke2fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04002016 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002017 command = "mke2fs -t " + File_System + " -m 0 " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00002018 LOGINFO("mke2fs command: %s\n", command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02002019 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08002020 Current_File_System = File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04002021 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002022 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04002023 return true;
2024 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002025 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04002026 return false;
2027 }
2028 } else
2029 return Wipe_RMRF();
2030
2031 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002032}
2033
2034bool TWPartition::Wipe_EXT4() {
Ethan Yonker25f20c12014-10-14 09:04:43 -05002035 Find_Actual_Block_Device();
2036 if (!Is_Present) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002037 LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
2038 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Ethan Yonker25f20c12014-10-14 09:04:43 -05002039 return false;
2040 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002041 if (!UnMount(true))
2042 return false;
2043
Matt Mower87413642017-01-17 21:14:46 -06002044#if defined(USE_EXT4)
Ethan Yonkerf27497f2014-02-09 11:48:33 -06002045 int ret;
2046 char *secontext = NULL;
2047
Greg Wallace4b44fef2015-12-29 15:33:24 -05002048 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Ethan Yonkerf27497f2014-02-09 11:48:33 -06002049
Dees Troy99c8dbf2014-03-10 16:53:58 +00002050 if (!selinux_handle || selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
Ethan Yonkerf27497f2014-02-09 11:48:33 -06002051 LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
2052 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
2053 } else {
2054 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
2055 }
2056 if (ret != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002057 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troya95f55c2013-08-17 13:14:43 +00002058 return false;
2059 } else {
bigbiff bigbiffc49d7062013-10-11 20:28:00 -04002060 string sedir = Mount_Point + "/lost+found";
2061 PartitionManager.Mount_By_Path(sedir.c_str(), true);
2062 rmdir(sedir.c_str());
2063 mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
Dees_Troya95f55c2013-08-17 13:14:43 +00002064 return true;
2065 }
2066#else
Dees_Troy43d8b002012-09-17 16:00:01 -04002067 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02002068 string Command;
Dees_Troy38bd7602012-09-14 13:33:53 -04002069
Greg Wallace4b44fef2015-12-29 15:33:24 -05002070 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04002071 Find_Actual_Block_Device();
2072 Command = "make_ext4fs";
2073 if (!Is_Decrypted && Length != 0) {
2074 // Only use length if we're not decrypted
2075 char len[32];
2076 sprintf(len, "%i", Length);
2077 Command += " -l ";
2078 Command += len;
2079 }
Dees_Troy5295d582013-09-06 15:51:08 +00002080 if (TWFunc::Path_Exists("/file_contexts")) {
2081 Command += " -S /file_contexts";
2082 }
2083 Command += " -a " + Mount_Point + " " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00002084 LOGINFO("make_ext4fs command: %s\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02002085 if (TWFunc::Exec_Cmd(Command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08002086 Current_File_System = "ext4";
Dees_Troye58d5262012-09-21 12:27:57 -04002087 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002088 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04002089 return true;
2090 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002091 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04002092 return false;
2093 }
2094 } else
Gary Peck43acadf2012-11-21 21:19:01 -08002095 return Wipe_EXT23("ext4");
Dees_Troya95f55c2013-08-17 13:14:43 +00002096#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04002097 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002098}
2099
2100bool TWPartition::Wipe_FAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02002101 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04002102
Matt Mower18794c82015-11-11 16:22:45 -06002103 if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002104 if (!UnMount(true))
2105 return false;
2106
Greg Wallace4b44fef2015-12-29 15:33:24 -05002107 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat"));
Dees_Troy38bd7602012-09-14 13:33:53 -04002108 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06002109 command = "mkfs.fat " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02002110 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08002111 Current_File_System = "vfat";
Dees_Troye58d5262012-09-21 12:27:57 -04002112 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002113 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04002114 return true;
2115 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002116 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04002117 return false;
2118 }
2119 return true;
2120 }
2121 else
2122 return Wipe_RMRF();
2123
2124 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002125}
2126
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002127bool TWPartition::Wipe_EXFAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02002128 string command;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002129
2130 if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
2131 if (!UnMount(true))
2132 return false;
2133
Greg Wallace4b44fef2015-12-29 15:33:24 -05002134 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkexfatfs"));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002135 Find_Actual_Block_Device();
2136 command = "mkexfatfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02002137 if (TWFunc::Exec_Cmd(command) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002138 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002139 gui_msg("done=Done.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002140 return true;
2141 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002142 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002143 return false;
2144 }
2145 return true;
2146 }
2147 return false;
2148}
2149
Dees_Troy38bd7602012-09-14 13:33:53 -04002150bool TWPartition::Wipe_MTD() {
2151 if (!UnMount(true))
2152 return false;
2153
Greg Wallace4b44fef2015-12-29 15:33:24 -05002154 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("MTD"));
Dees_Troy38bd7602012-09-14 13:33:53 -04002155
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02002156 mtd_scan_partitions();
2157 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
2158 if (mtd == NULL) {
2159 LOGERR("No mtd partition named '%s'", MTD_Name.c_str());
2160 return false;
2161 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002162
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02002163 MtdWriteContext* ctx = mtd_write_partition(mtd);
2164 if (ctx == NULL) {
2165 LOGERR("Can't write '%s', failed to format.", MTD_Name.c_str());
2166 return false;
2167 }
2168 if (mtd_erase_blocks(ctx, -1) == -1) {
2169 mtd_write_close(ctx);
2170 LOGERR("Failed to format '%s'", MTD_Name.c_str());
2171 return false;
2172 }
2173 if (mtd_write_close(ctx) != 0) {
2174 LOGERR("Failed to close '%s'", MTD_Name.c_str());
2175 return false;
2176 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08002177 Current_File_System = "yaffs2";
Dees_Troye58d5262012-09-21 12:27:57 -04002178 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002179 gui_msg("done=Done.");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02002180 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002181}
2182
2183bool TWPartition::Wipe_RMRF() {
Dees_Troy38bd7602012-09-14 13:33:53 -04002184 if (!Mount(true))
2185 return false;
Ethan Yonker726a0202014-12-16 20:01:38 -06002186 // This is the only wipe that leaves the partition mounted, so we
2187 // must manually remove the partition from MTP if it is a storage
2188 // partition.
2189 if (Is_Storage)
2190 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04002191
Ethan Yonker74db1572015-10-28 12:44:49 -05002192 gui_msg(Msg("remove_all=Removing all files under '{1}'")(Mount_Point));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002193 TWFunc::removeDir(Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002194 Recreate_AndSec_Folder();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002195 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002196}
2197
Dees_Troye5017042013-08-29 16:38:55 +00002198bool TWPartition::Wipe_F2FS() {
Vojtech Bocek05534202013-09-11 08:11:56 +02002199 string command;
Dees_Troye5017042013-08-29 16:38:55 +00002200
2201 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
2202 if (!UnMount(true))
2203 return false;
2204
Greg Wallace4b44fef2015-12-29 15:33:24 -05002205 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.f2fs"));
Dees_Troye5017042013-08-29 16:38:55 +00002206 Find_Actual_Block_Device();
Greg Wallace558aef72016-01-19 21:14:30 -05002207 command = "mkfs.f2fs -t 0";
dhacker29a3fa75f2015-01-17 19:42:33 -05002208 if (!Is_Decrypted && Length != 0) {
2209 // Only use length if we're not decrypted
2210 char len[32];
2211 int mod_length = Length;
2212 if (Length < 0)
2213 mod_length *= -1;
2214 sprintf(len, "%i", mod_length);
2215 command += " -r ";
2216 command += len;
2217 }
2218 command += " " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02002219 if (TWFunc::Exec_Cmd(command) == 0) {
Dees_Troye5017042013-08-29 16:38:55 +00002220 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002221 gui_msg("done=Done.");
Dees_Troye5017042013-08-29 16:38:55 +00002222 return true;
2223 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002224 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troye5017042013-08-29 16:38:55 +00002225 return false;
2226 }
2227 return true;
2228 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002229 LOGINFO("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
Dees_Troye5017042013-08-29 16:38:55 +00002230 return Wipe_RMRF();
2231 }
2232 return false;
2233}
2234
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002235bool TWPartition::Wipe_NTFS() {
2236 string command;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002237 string Ntfsmake_Binary;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002238
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002239 if (TWFunc::Path_Exists("/sbin/mkntfs"))
2240 Ntfsmake_Binary = "mkntfs";
2241 else if (TWFunc::Path_Exists("/sbin/mkfs.ntfs"))
2242 Ntfsmake_Binary = "mkfs.ntfs";
2243 else
2244 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002245
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002246 if (!UnMount(true))
2247 return false;
2248
Greg Wallace4b44fef2015-12-29 15:33:24 -05002249 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)(Ntfsmake_Binary));
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002250 Find_Actual_Block_Device();
2251 command = "/sbin/" + Ntfsmake_Binary + " " + Actual_Block_Device;
2252 if (TWFunc::Exec_Cmd(command) == 0) {
2253 Recreate_AndSec_Folder();
2254 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002255 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002256 } else {
2257 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
2258 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002259 }
2260 return false;
2261}
2262
Dees_Troy51a0e822012-09-05 15:24:24 -04002263bool TWPartition::Wipe_Data_Without_Wiping_Media() {
Ethan Yonker83e82572014-04-04 10:59:28 -05002264#ifdef TW_OEM_BUILD
2265 // In an OEM Build we want to do a full format
2266 return Wipe_Encryption();
2267#else
Ethan Yonker66a19492015-12-10 10:19:45 -06002268 bool ret = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04002269
Dees_Troy38bd7602012-09-14 13:33:53 -04002270 if (!Mount(true))
2271 return false;
2272
Ethan Yonker74db1572015-10-28 12:44:49 -05002273 gui_msg("wiping_data=Wiping data without wiping /data/media ...");
Ethan Yonker66a19492015-12-10 10:19:45 -06002274 ret = Wipe_Data_Without_Wiping_Media_Func(Mount_Point + "/");
2275 if (ret)
2276 gui_msg("done=Done.");
2277 return ret;
2278#endif // ifdef TW_OEM_BUILD
2279}
2280
2281bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unused) {
2282 string dir;
Dees_Troy38bd7602012-09-14 13:33:53 -04002283
2284 DIR* d;
Ethan Yonker66a19492015-12-10 10:19:45 -06002285 d = opendir(parent.c_str());
Dees_Troy16b74352012-11-14 22:27:31 +00002286 if (d != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002287 struct dirent* de;
2288 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002289 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05002290
Ethan Yonker66a19492015-12-10 10:19:45 -06002291 dir = parent;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002292 dir.append(de->d_name);
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002293 if (wipe_exclusions.check_skip_dirs(dir)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002294 LOGINFO("skipped '%s'\n", dir.c_str());
2295 continue;
2296 }
Dees_Troyce675462013-01-09 19:48:21 +00002297 if (de->d_type == DT_DIR) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002298 dir.append("/");
2299 if (!Wipe_Data_Without_Wiping_Media_Func(dir)) {
2300 closedir(d);
2301 return false;
2302 }
2303 rmdir(dir.c_str());
bigbiff bigbiff98f1f902013-01-19 18:46:13 -05002304 } else if (de->d_type == DT_REG || de->d_type == DT_LNK || de->d_type == DT_FIFO || de->d_type == DT_SOCK) {
nkk719efbe762017-06-13 19:49:05 +03002305 if (unlink(dir.c_str()) != 0)
Ethan Yonker79f88bd2016-12-09 14:52:12 -06002306 LOGINFO("Unable to unlink '%s': %s\n", dir.c_str(), strerror(errno));
Dees_Troyce675462013-01-09 19:48:21 +00002307 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002308 }
2309 closedir(d);
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05002310
Dees_Troy16b74352012-11-14 22:27:31 +00002311 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04002312 }
Ethan Yonker74db1572015-10-28 12:44:49 -05002313 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy16b74352012-11-14 22:27:31 +00002314 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002315}
2316
bigbiffce8f83c2015-12-12 18:30:21 -05002317bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002318 string Full_FileName;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002319 twrpTar tar;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05002320
Dees_Troy43d8b002012-09-17 16:00:01 -04002321 if (!Mount(true))
2322 return false;
2323
Dees_Troya13d74f2013-03-24 08:54:55 -05002324 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up");
Ethan Yonker74db1572015-10-28 12:44:49 -05002325 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002326
Ethan Yonker472f5062016-02-25 13:47:30 -06002327 DataManager::GetValue(TW_USE_COMPRESSION_VAR, tar.use_compression);
Matt Mowerbb81e5d2014-03-20 18:05:41 -05002328
Dees_Troy83bd4832013-05-04 12:39:56 +00002329#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
Ethan Yonker472f5062016-02-25 13:47:30 -06002330 if (Can_Encrypt_Backup) {
2331 DataManager::GetValue("tw_encrypt_backup", tar.use_encryption);
2332 if (tar.use_encryption) {
2333 if (Use_Userdata_Encryption)
2334 tar.userdata_encryption = tar.use_encryption;
2335 string Password;
2336 DataManager::GetValue("tw_backup_password", Password);
2337 tar.setpassword(Password);
2338 } else {
2339 tar.use_encryption = 0;
2340 }
Dees_Troy83bd4832013-05-04 12:39:56 +00002341 }
2342#endif
Dees_Troy43d8b002012-09-17 16:00:01 -04002343
Ethan Yonker472f5062016-02-25 13:47:30 -06002344 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002345 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker01f4e032017-02-03 15:30:52 -06002346 if (Has_Data_Media)
2347 gui_msg(Msg(msg::kWarning, "backup_storage_warning=Backups of {1} do not include any files in internal storage such as pictures or downloads.")(Display_Name));
bigbiffce8f83c2015-12-12 18:30:21 -05002348 tar.part_settings = part_settings;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002349 tar.backup_exclusions = &backup_exclusions;
Dees Troye0a433a2013-12-02 04:10:37 +00002350 tar.setdir(Backup_Path);
2351 tar.setfn(Full_FileName);
2352 tar.setsize(Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002353 tar.partition_name = Backup_Name;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002354 tar.backup_folder = part_settings->Backup_Folder;
bigbiffce8f83c2015-12-12 18:30:21 -05002355 if (tar.createTarFork(tar_fork_pid) != 0)
Dees Troye0a433a2013-12-02 04:10:37 +00002356 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04002357 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002358}
2359
bigbiffce8f83c2015-12-12 18:30:21 -05002360bool TWPartition::Backup_Image(PartitionSettings *part_settings) {
2361 string Full_FileName, adb_file_name;
igoriok87e3d932013-01-31 21:03:53 +02002362
Ethan Yonker74db1572015-10-28 12:44:49 -05002363 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2364 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002365
Ethan Yonker472f5062016-02-25 13:47:30 -06002366 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Dees_Troy43d8b002012-09-17 16:00:01 -04002367
bigbiffce8f83c2015-12-12 18:30:21 -05002368 if (part_settings->adbbackup) {
2369 Full_FileName = TW_ADB_BACKUP;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002370 adb_file_name = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002371 }
2372 else
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002373 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002374
2375 part_settings->total_restore_size = Backup_Size;
2376
2377 if (part_settings->adbbackup) {
2378 if (!twadbbu::Write_TWIMG(adb_file_name, Backup_Size))
2379 return false;
2380 }
2381
2382 if (!Raw_Read_Write(part_settings))
Ethan Yonker472f5062016-02-25 13:47:30 -06002383 return false;
2384
bigbiffce8f83c2015-12-12 18:30:21 -05002385 if (part_settings->adbbackup) {
2386 if (!twadbbu::Write_TWEOF())
2387 return false;
Dees_Troy7c2dec82012-09-26 09:49:14 -04002388 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002389 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002390}
2391
bigbiffce8f83c2015-12-12 18:30:21 -05002392bool TWPartition::Raw_Read_Write(PartitionSettings *part_settings) {
2393 unsigned long long RW_Block_Size, Remain = Backup_Size;
2394 int src_fd = -1, dest_fd = -1;
2395 ssize_t bs;
Ethan Yonker472f5062016-02-25 13:47:30 -06002396 bool ret = false;
2397 void* buffer = NULL;
2398 unsigned long long backedup_size = 0;
bigbiffce8f83c2015-12-12 18:30:21 -05002399 string srcfn, destfn;
Ethan Yonker472f5062016-02-25 13:47:30 -06002400
bigbiffce8f83c2015-12-12 18:30:21 -05002401 if (part_settings->PM_Method == PM_BACKUP) {
2402 srcfn = Actual_Block_Device;
2403 if (part_settings->adbbackup)
2404 destfn = TW_ADB_BACKUP;
2405 else
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002406 destfn = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002407 }
2408 else {
2409 destfn = Actual_Block_Device;
2410 if (part_settings->adbbackup) {
2411 srcfn = TW_ADB_RESTORE;
2412 } else {
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002413 srcfn = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002414 Remain = TWFunc::Get_File_Size(srcfn);
2415 }
2416 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002417
bigbiffce8f83c2015-12-12 18:30:21 -05002418 src_fd = open(srcfn.c_str(), O_RDONLY | O_LARGEFILE);
Ethan Yonker472f5062016-02-25 13:47:30 -06002419 if (src_fd < 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05002420 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(srcfn.c_str())(strerror(errno)));
Ethan Yonker472f5062016-02-25 13:47:30 -06002421 return false;
2422 }
bigbiffce8f83c2015-12-12 18:30:21 -05002423
2424 dest_fd = open(destfn.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR);
Ethan Yonker472f5062016-02-25 13:47:30 -06002425 if (dest_fd < 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05002426 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(destfn.c_str())(strerror(errno)));
Ethan Yonker472f5062016-02-25 13:47:30 -06002427 goto exit;
2428 }
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04002429
bigbiffce8f83c2015-12-12 18:30:21 -05002430 LOGINFO("Reading '%s', writing '%s'\n", srcfn.c_str(), destfn.c_str());
2431
2432 if (part_settings->adbbackup) {
2433 RW_Block_Size = MAX_ADB_READ;
2434 bs = MAX_ADB_READ;
2435 }
2436 else {
2437 RW_Block_Size = 1048576LLU; // 1MB
2438 bs = (ssize_t)(RW_Block_Size);
2439 }
2440
Ethan Yonker472f5062016-02-25 13:47:30 -06002441 buffer = malloc((size_t)bs);
2442 if (!buffer) {
2443 LOGINFO("Raw_Read_Write failed to malloc\n");
2444 goto exit;
2445 }
bigbiffce8f83c2015-12-12 18:30:21 -05002446
2447 if (part_settings->progress)
2448 part_settings->progress->SetPartitionSize(part_settings->total_restore_size);
2449
Ethan Yonker472f5062016-02-25 13:47:30 -06002450 while (Remain > 0) {
2451 if (Remain < RW_Block_Size)
bigbiffce8f83c2015-12-12 18:30:21 -05002452 bs = (ssize_t)(Remain);
Matt Mowera8a89d12016-12-30 18:10:37 -06002453 if (read(src_fd, buffer, bs) != bs) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002454 LOGINFO("Error reading source fd (%s)\n", strerror(errno));
2455 goto exit;
2456 }
2457 if (write(dest_fd, buffer, bs) != bs) {
2458 LOGINFO("Error writing destination fd (%s)\n", strerror(errno));
2459 goto exit;
2460 }
2461 backedup_size += (unsigned long long)(bs);
Matt Mower029a82d2017-01-08 13:12:38 -06002462 Remain -= (unsigned long long)(bs);
bigbiffce8f83c2015-12-12 18:30:21 -05002463 if (part_settings->progress)
2464 part_settings->progress->UpdateSize(backedup_size);
Ethan Yonker472f5062016-02-25 13:47:30 -06002465 if (PartitionManager.Check_Backup_Cancel() != 0)
2466 goto exit;
2467 }
bigbiffce8f83c2015-12-12 18:30:21 -05002468 if (part_settings->progress)
2469 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker472f5062016-02-25 13:47:30 -06002470 fsync(dest_fd);
nailyka083dc62016-11-11 21:41:28 +01002471
2472 if (!part_settings->adbbackup && part_settings->PM_Method == PM_BACKUP) {
2473 tw_set_default_metadata(destfn.c_str());
2474 LOGINFO("Restored default metadata for %s\n", destfn.c_str());
2475 }
2476
Ethan Yonker472f5062016-02-25 13:47:30 -06002477 ret = true;
2478exit:
2479 if (src_fd >= 0)
2480 close(src_fd);
2481 if (dest_fd >= 0)
2482 close(dest_fd);
2483 if (buffer)
2484 free(buffer);
2485 return ret;
2486}
2487
bigbiffce8f83c2015-12-12 18:30:21 -05002488bool TWPartition::Backup_Dump_Image(PartitionSettings *part_settings) {
Vojtech Bocek05534202013-09-11 08:11:56 +02002489 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04002490
Ethan Yonker74db1572015-10-28 12:44:49 -05002491 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2492 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002493
bigbiffce8f83c2015-12-12 18:30:21 -05002494 if (part_settings->progress)
2495 part_settings->progress->SetPartitionSize(Backup_Size);
Dees_Troy43d8b002012-09-17 16:00:01 -04002496
Ethan Yonker472f5062016-02-25 13:47:30 -06002497 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002498 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04002499
2500 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
bigbiffce8f83c2015-12-12 18:30:21 -05002501
Dees_Troy2673cec2013-04-02 20:22:16 +00002502 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02002503 TWFunc::Exec_Cmd(Command);
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06002504 tw_set_default_metadata(Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04002505 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
2506 // 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 -06002507 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName));
Dees_Troy7c2dec82012-09-26 09:49:14 -04002508 return false;
2509 }
bigbiffce8f83c2015-12-12 18:30:21 -05002510 if (part_settings->progress)
2511 part_settings->progress->UpdateSize(Backup_Size);
2512
Dees_Troy43d8b002012-09-17 16:00:01 -04002513 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002514}
2515
bigbiffce8f83c2015-12-12 18:30:21 -05002516unsigned long long TWPartition::Get_Restore_Size(PartitionSettings *part_settings) {
2517 if (!part_settings->adbbackup) {
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002518 InfoManager restore_info(part_settings->Backup_Folder + "/" + Backup_Name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -05002519 if (restore_info.LoadValues() == 0) {
2520 if (restore_info.GetValue("backup_size", Restore_Size) == 0) {
2521 LOGINFO("Read info file, restore size is %llu\n", Restore_Size);
2522 return Restore_Size;
2523 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002524 }
2525 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002526
Matt Mower029a82d2017-01-08 13:12:38 -06002527 string Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
2528 string Restore_File_System = Get_Restore_File_System(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002529
2530 if (Is_Image(Restore_File_System)) {
2531 Restore_Size = TWFunc::Get_File_Size(Full_FileName);
2532 return Restore_Size;
2533 }
2534
2535 twrpTar tar;
2536 tar.setdir(Backup_Path);
2537 tar.setfn(Full_FileName);
bigbiffce8f83c2015-12-12 18:30:21 -05002538 tar.backup_name = Full_FileName;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002539#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2540 string Password;
2541 DataManager::GetValue("tw_restore_password", Password);
2542 if (!Password.empty())
2543 tar.setpassword(Password);
2544#endif
2545 tar.partition_name = Backup_Name;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002546 tar.backup_folder = part_settings->Backup_Folder;
bigbiffce8f83c2015-12-12 18:30:21 -05002547 tar.part_settings = part_settings;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002548 Restore_Size = tar.get_size();
2549 return Restore_Size;
2550}
2551
bigbiffce8f83c2015-12-12 18:30:21 -05002552bool TWPartition::Restore_Tar(PartitionSettings *part_settings) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002553 string Full_FileName;
Dees Troy4159aed2014-02-28 17:24:43 +00002554 bool ret = false;
bigbiffce8f83c2015-12-12 18:30:21 -05002555 string Restore_File_System = Get_Restore_File_System(part_settings);
Dees_Troy43d8b002012-09-17 16:00:01 -04002556
Dees_Troye58d5262012-09-21 12:27:57 -04002557 if (Has_Android_Secure) {
Dees_Troye58d5262012-09-21 12:27:57 -04002558 if (!Wipe_AndSec())
2559 return false;
Gary Peck43acadf2012-11-21 21:19:01 -08002560 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002561 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
Ethan Yonker5eac2222014-06-11 12:22:55 -05002562 if (Has_Data_Media && Mount_Point == "/data" && Restore_File_System != Current_File_System) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002563 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 -05002564 if (!Wipe_Data_Without_Wiping_Media())
2565 return false;
2566 } else {
2567 if (!Wipe(Restore_File_System))
2568 return false;
2569 }
Dees_Troye58d5262012-09-21 12:27:57 -04002570 }
Matt Mower3c366972015-12-25 19:28:31 -06002571 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002572 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002573
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002574 // Remount as read/write as needed so we can restore the backup
2575 if (!ReMount_RW(true))
Dees_Troy43d8b002012-09-17 16:00:01 -04002576 return false;
2577
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002578 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker87af5632014-02-10 11:56:35 -06002579 twrpTar tar;
bigbiffce8f83c2015-12-12 18:30:21 -05002580 tar.part_settings = part_settings;
Ethan Yonker87af5632014-02-10 11:56:35 -06002581 tar.setdir(Backup_Path);
2582 tar.setfn(Full_FileName);
2583 tar.backup_name = Backup_Name;
2584#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2585 string Password;
2586 DataManager::GetValue("tw_restore_password", Password);
2587 if (!Password.empty())
2588 tar.setpassword(Password);
2589#endif
bigbiffce8f83c2015-12-12 18:30:21 -05002590 part_settings->progress->SetPartitionSize(Get_Restore_Size(part_settings));
2591 if (tar.extractTarFork() != 0)
Dees Troy4159aed2014-02-28 17:24:43 +00002592 ret = false;
2593 else
2594 ret = true;
2595#ifdef HAVE_CAPABILITIES
2596 // Restore capabilities to the run-as binary
2597 if (Mount_Point == "/system" && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
2598 struct vfs_cap_data cap_data;
2599 uint64_t capabilities = (1 << CAP_SETUID) | (1 << CAP_SETGID);
2600
2601 memset(&cap_data, 0, sizeof(cap_data));
2602 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
2603 cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
2604 cap_data.data[0].inheritable = 0;
2605 cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
2606 cap_data.data[1].inheritable = 0;
2607 if (setxattr("/system/bin/run-as", XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
2608 LOGINFO("Failed to reset capabilities of /system/bin/run-as binary.\n");
2609 } else {
2610 LOGINFO("Reset capabilities of /system/bin/run-as binary successful.\n");
2611 }
2612 }
2613#endif
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002614 if (Mount_Read_Only || Mount_Flags & MS_RDONLY)
2615 // Remount as read only when restoration is complete
2616 ReMount(true);
2617
Dees Troy4159aed2014-02-28 17:24:43 +00002618 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04002619}
2620
bigbiffce8f83c2015-12-12 18:30:21 -05002621bool TWPartition::Restore_Image(PartitionSettings *part_settings) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002622 string Full_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002623 string Restore_File_System = Get_Restore_File_System(part_settings);
Dees_Troy43d8b002012-09-17 16:00:01 -04002624
Matt Mower3c366972015-12-25 19:28:31 -06002625 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002626 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
bigbiffce8f83c2015-12-12 18:30:21 -05002627
2628 if (part_settings->adbbackup)
2629 Full_FileName = TW_ADB_RESTORE;
2630 else
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002631 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Gary Peck15e623d2012-11-21 21:07:58 -08002632
Ethan Yonker96af84a2015-01-05 14:58:36 -06002633 if (Restore_File_System == "emmc") {
bigbiffce8f83c2015-12-12 18:30:21 -05002634 if (!part_settings->adbbackup)
2635 part_settings->total_restore_size = (uint64_t)(TWFunc::Get_File_Size(Full_FileName));
2636 if (!Raw_Read_Write(part_settings))
Ethan Yonker96af84a2015-01-05 14:58:36 -06002637 return false;
2638 } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") {
bigbiffce8f83c2015-12-12 18:30:21 -05002639 if (!Flash_Image_FI(Full_FileName, part_settings->progress))
2640 return false;
2641 }
2642
2643 if (part_settings->adbbackup) {
2644 if (!twadbbu::Write_TWEOF())
Ethan Yonker96af84a2015-01-05 14:58:36 -06002645 return false;
Gary Peck15e623d2012-11-21 21:07:58 -08002646 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002647 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002648}
Dees_Troy5bf43922012-09-07 16:07:55 -04002649
2650bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy0550cfb2012-10-13 11:56:13 -04002651 bool ret = false, Was_Already_Mounted = false;
Dees_Troy51127312012-09-08 13:08:49 -04002652
Ethan Yonker1b190162016-12-05 15:25:19 -06002653 Find_Actual_Block_Device();
2654
2655 if (!Can_Be_Mounted && !Is_Encrypted) {
2656 if (TWFunc::Path_Exists(Actual_Block_Device) && Find_Partition_Size()) {
2657 Used = Size;
2658 Backup_Size = Size;
2659 return true;
2660 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002661 return false;
Ethan Yonker1b190162016-12-05 15:25:19 -06002662 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002663
Dees_Troy0550cfb2012-10-13 11:56:13 -04002664 Was_Already_Mounted = Is_Mounted();
Dees_Troy38bd7602012-09-14 13:33:53 -04002665 if (Removable || Is_Encrypted) {
2666 if (!Mount(false))
2667 return true;
2668 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04002669 return false;
Dees_Troy51127312012-09-08 13:08:49 -04002670
2671 ret = Get_Size_Via_statfs(Display_Error);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002672 if (!ret || Size == 0) {
2673 if (!Get_Size_Via_df(Display_Error)) {
2674 if (!Was_Already_Mounted)
2675 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -04002676 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002677 }
2678 }
Dees_Troy51127312012-09-08 13:08:49 -04002679
Dees_Troy5bf43922012-09-07 16:07:55 -04002680 if (Has_Data_Media) {
2681 if (Mount(Display_Error)) {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002682 Used = backup_exclusions.Get_Folder_Size(Mount_Point);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002683 Backup_Size = Used;
2684 int bak = (int)(Used / 1048576LLU);
Dees_Troy51127312012-09-08 13:08:49 -04002685 int fre = (int)(Free / 1048576LLU);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002686 LOGINFO("Data backup size is %iMB, free: %iMB.\n", bak, fre);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002687 } else {
2688 if (!Was_Already_Mounted)
2689 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002690 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002691 }
Dees_Troye58d5262012-09-21 12:27:57 -04002692 } else if (Has_Android_Secure) {
2693 if (Mount(Display_Error))
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002694 Backup_Size = backup_exclusions.Get_Folder_Size(Backup_Path);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002695 else {
2696 if (!Was_Already_Mounted)
2697 UnMount(false);
Dees_Troye58d5262012-09-21 12:27:57 -04002698 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002699 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002700 }
Dees_Troy0550cfb2012-10-13 11:56:13 -04002701 if (!Was_Already_Mounted)
2702 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002703 return true;
Dees_Troy51127312012-09-08 13:08:49 -04002704}
Dees_Troy38bd7602012-09-14 13:33:53 -04002705
Ethan Yonker6e8c27a2016-12-22 17:55:57 -06002706bool TWPartition::Find_Wildcard_Block_Devices(const string& Device) {
2707 int mount_point_index = 0; // we will need to create separate mount points for each partition found and we use this index to name each one
2708 string Path = TWFunc::Get_Path(Device);
2709 string Dev = TWFunc::Get_Filename(Device);
2710 size_t wildcard_index = Dev.find("*");
2711 if (wildcard_index != string::npos)
2712 Dev = Dev.substr(0, wildcard_index);
2713 wildcard_index = Dev.size();
2714 DIR* d = opendir(Path.c_str());
2715 if (d == NULL) {
2716 LOGINFO("Error opening '%s': %s\n", Path.c_str(), strerror(errno));
2717 return false;
2718 }
2719 struct dirent* de;
2720 while ((de = readdir(d)) != NULL) {
2721 if (de->d_type != DT_BLK || strlen(de->d_name) <= wildcard_index || strncmp(de->d_name, Dev.c_str(), wildcard_index) != 0)
2722 continue;
2723
2724 string item = Path + "/";
2725 item.append(de->d_name);
2726 if (PartitionManager.Find_Partition_By_Block_Device(item))
2727 continue;
2728 TWPartition *part = new TWPartition;
2729 char buffer[MAX_FSTAB_LINE_LENGTH];
2730 sprintf(buffer, "%s %s-%i auto defaults defaults", item.c_str(), Mount_Point.c_str(), ++mount_point_index);
2731 part->Process_Fstab_Line(buffer, false, NULL);
2732 char display[MAX_FSTAB_LINE_LENGTH];
2733 sprintf(display, "%s %i", Storage_Name.c_str(), mount_point_index);
2734 part->Storage_Name = display;
2735 part->Display_Name = display;
2736 part->Primary_Block_Device = item;
2737 part->Wildcard_Block_Device = false;
2738 part->Is_SubPartition = true;
2739 part->SubPartition_Of = Mount_Point;
2740 part->Is_Storage = Is_Storage;
2741 part->Can_Be_Mounted = true;
2742 part->Removable = true;
2743 part->Can_Be_Wiped = Can_Be_Wiped;
2744 part->Wipe_Available_in_GUI = Wipe_Available_in_GUI;
2745 part->Find_Actual_Block_Device();
2746 part->Update_Size(false);
2747 Has_SubPartition = true;
2748 PartitionManager.Output_Partition(part);
2749 PartitionManager.Add_Partition(part);
2750 }
2751 closedir(d);
2752 return (mount_point_index > 0);
2753}
2754
Dees_Troy38bd7602012-09-14 13:33:53 -04002755void TWPartition::Find_Actual_Block_Device(void) {
Ethan Yonker6e8c27a2016-12-22 17:55:57 -06002756 if (!Sysfs_Entry.empty() && Primary_Block_Device.empty() && Decrypted_Block_Device.empty()) {
2757 /* Sysfs_Entry.empty() indicates if this is a sysfs entry that begins with /device/
2758 * If we have a syfs entry then we are looking for this device from a uevent add.
2759 * The uevent add will set the primary block device based on the data we receive from
2760 * after checking for adopted storage. If the device ends up being adopted, then the
2761 * decrypted block device will be set instead of the primary block device. */
2762 Is_Present = false;
2763 return;
2764 }
2765 if (Wildcard_Block_Device && !Is_Adopted_Storage) {
2766 Is_Present = false;
2767 Actual_Block_Device = "";
2768 Can_Be_Mounted = false;
2769 if (!Find_Wildcard_Block_Devices(Primary_Block_Device)) {
2770 string Dev = Primary_Block_Device.substr(0, Primary_Block_Device.find("*"));
2771 if (TWFunc::Path_Exists(Dev)) {
2772 Is_Present = true;
2773 Can_Be_Mounted = true;
2774 Actual_Block_Device = Dev;
2775 }
2776 }
2777 return;
2778 } else if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002779 Actual_Block_Device = Decrypted_Block_Device;
Ethan Yonker1b190162016-12-05 15:25:19 -06002780 if (TWFunc::Path_Exists(Decrypted_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002781 Is_Present = true;
Ethan Yonker1b190162016-12-05 15:25:19 -06002782 return;
2783 }
2784 } else if (SlotSelect && TWFunc::Path_Exists(Primary_Block_Device + PartitionManager.Get_Active_Slot_Suffix())) {
2785 Actual_Block_Device = Primary_Block_Device + PartitionManager.Get_Active_Slot_Suffix();
2786 unlink(Primary_Block_Device.c_str());
2787 symlink(Actual_Block_Device.c_str(), Primary_Block_Device.c_str()); // we create a non-slot symlink pointing to the currently selected slot which may assist zips with installing
2788 Is_Present = true;
2789 return;
Dees_Troy43d8b002012-09-17 16:00:01 -04002790 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002791 Is_Present = true;
2792 Actual_Block_Device = Primary_Block_Device;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002793 return;
2794 }
Ethan Yonker1b190162016-12-05 15:25:19 -06002795 if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy3f04d032012-10-07 18:20:09 -04002796 Actual_Block_Device = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -04002797 Is_Present = true;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002798 } else {
Dees_Troy38bd7602012-09-14 13:33:53 -04002799 Is_Present = false;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002800 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002801}
2802
2803void TWPartition::Recreate_Media_Folder(void) {
2804 string Command;
Ethan Yonker66a19492015-12-10 10:19:45 -06002805 string Media_Path = Mount_Point + "/media";
Dees_Troy38bd7602012-09-14 13:33:53 -04002806
Ethan Yonkerbd7492d2016-12-07 13:55:01 -06002807 if (Is_FBE) {
2808 LOGINFO("Not recreating media folder on FBE\n");
2809 return;
2810 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002811 if (!Mount(true)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002812 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Media_Path));
2813 } else if (!TWFunc::Path_Exists(Media_Path)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002814 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker66a19492015-12-10 10:19:45 -06002815 LOGINFO("Recreating %s folder.\n", Media_Path.c_str());
2816 mkdir(Media_Path.c_str(), 0770);
xiaolu9416f4f2015-06-04 08:22:23 +08002817 string Internal_path = DataManager::GetStrValue("tw_internal_path");
2818 if (!Internal_path.empty()) {
2819 LOGINFO("Recreating %s folder.\n", Internal_path.c_str());
2820 mkdir(Internal_path.c_str(), 0770);
2821 }
2822#ifdef TW_INTERNAL_STORAGE_PATH
2823 mkdir(EXPAND(TW_INTERNAL_STORAGE_PATH), 0770);
2824#endif
Matt Mower87413642017-01-17 21:14:46 -06002825
thata3d31fb2014-12-21 22:27:40 +01002826 // Afterwards, we will try to set the
2827 // default metadata that we were hopefully able to get during
2828 // early boot.
Ethan Yonker66a19492015-12-10 10:19:45 -06002829 tw_set_default_metadata(Media_Path.c_str());
xiaolu9416f4f2015-06-04 08:22:23 +08002830 if (!Internal_path.empty())
2831 tw_set_default_metadata(Internal_path.c_str());
Matt Mower87413642017-01-17 21:14:46 -06002832
Ethan Yonker5eac2222014-06-11 12:22:55 -05002833 // Toggle mount to ensure that "internal sdcard" gets mounted
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002834 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker5eac2222014-06-11 12:22:55 -05002835 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy38bd7602012-09-14 13:33:53 -04002836 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002837}
Dees_Troye58d5262012-09-21 12:27:57 -04002838
2839void TWPartition::Recreate_AndSec_Folder(void) {
Dees_Troye58d5262012-09-21 12:27:57 -04002840 if (!Has_Android_Secure)
2841 return;
Dees_Troy2673cec2013-04-02 20:22:16 +00002842 LOGINFO("Creating %s: %s\n", Backup_Display_Name.c_str(), Symlink_Path.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04002843 if (!Mount(true)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002844 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Backup_Name));
Dees_Troye58d5262012-09-21 12:27:57 -04002845 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002846 LOGINFO("Recreating %s folder.\n", Backup_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002847 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05002848 mkdir(Symlink_Path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002849 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002850 }
2851}
bigbiff7cb4c332014-11-26 20:36:07 -05002852
2853uint64_t TWPartition::Get_Max_FileSize() {
2854 uint64_t maxFileSize = 0;
2855 const uint64_t constGB = (uint64_t) 1024 * 1024 * 1024;
2856 const uint64_t constTB = (uint64_t) constGB * 1024;
2857 const uint64_t constPB = (uint64_t) constTB * 1024;
bigbiff0c532032014-12-21 13:41:26 -05002858 if (Current_File_System == "ext4")
2859 maxFileSize = 16 * constTB; //16 TB
2860 else if (Current_File_System == "vfat")
2861 maxFileSize = 4 * constGB; //4 GB
2862 else if (Current_File_System == "ntfs")
2863 maxFileSize = 256 * constTB; //256 TB
2864 else if (Current_File_System == "exfat")
2865 maxFileSize = 16 * constPB; //16 PB
2866 else if (Current_File_System == "ext3")
2867 maxFileSize = 2 * constTB; //2 TB
2868 else if (Current_File_System == "f2fs")
2869 maxFileSize = 3.94 * constTB; //3.94 TB
bigbiff7cb4c332014-11-26 20:36:07 -05002870 else
2871 maxFileSize = 100000000L;
2872 return maxFileSize - 1;
2873}
2874
bigbiffce8f83c2015-12-12 18:30:21 -05002875bool TWPartition::Flash_Image(PartitionSettings *part_settings) {
2876 string Restore_File_System, full_filename;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002877
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002878 full_filename = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002879
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002880 LOGINFO("Image filename is: %s\n", Backup_FileName.c_str());
bigbiffce8f83c2015-12-12 18:30:21 -05002881
2882 if (Backup_Method == BM_FILES) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002883 LOGERR("Cannot flash images to file systems\n");
2884 return false;
2885 } else if (!Can_Flash_Img) {
2886 LOGERR("Cannot flash images to partitions %s\n", Display_Name.c_str());
2887 return false;
2888 } else {
2889 if (!Find_Partition_Size()) {
2890 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
2891 return false;
2892 }
bigbiffce8f83c2015-12-12 18:30:21 -05002893 unsigned long long image_size = TWFunc::Get_File_Size(full_filename);
Ethan Yonker96af84a2015-01-05 14:58:36 -06002894 if (image_size > Size) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002895 LOGINFO("Size (%llu bytes) of image '%s' is larger than target device '%s' (%llu bytes)\n",
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002896 image_size, Backup_FileName.c_str(), Actual_Block_Device.c_str(), Size);
Ethan Yonker74db1572015-10-28 12:44:49 -05002897 gui_err("img_size_err=Size of image is larger than target device");
Ethan Yonker96af84a2015-01-05 14:58:36 -06002898 return false;
2899 }
bigbiffce8f83c2015-12-12 18:30:21 -05002900 if (Backup_Method == BM_DD) {
2901 if (!part_settings->adbbackup) {
2902 if (Is_Sparse_Image(full_filename)) {
2903 return Flash_Sparse_Image(full_filename);
2904 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002905 }
bigbiffce8f83c2015-12-12 18:30:21 -05002906 return Raw_Read_Write(part_settings);
2907 } else if (Backup_Method == BM_FLASH_UTILS) {
2908 return Flash_Image_FI(full_filename, NULL);
Ethan Yonker472f5062016-02-25 13:47:30 -06002909 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002910 }
2911
2912 LOGERR("Unknown flash method for '%s'\n", Mount_Point.c_str());
2913 return false;
2914}
2915
Ethan Yonker472f5062016-02-25 13:47:30 -06002916bool TWPartition::Is_Sparse_Image(const string& Filename) {
HashBanged974bb2016-01-30 14:20:09 -05002917 uint32_t magic = 0;
2918 int fd = open(Filename.c_str(), O_RDONLY);
2919 if (fd < 0) {
2920 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2921 return false;
2922 }
bigbiffce8f83c2015-12-12 18:30:21 -05002923
HashBanged974bb2016-01-30 14:20:09 -05002924 if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) {
2925 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2926 close(fd);
2927 return false;
2928 }
2929 close(fd);
Ethan Yonker472f5062016-02-25 13:47:30 -06002930 if (magic == SPARSE_HEADER_MAGIC)
2931 return true;
2932 return false;
2933}
2934
2935bool TWPartition::Flash_Sparse_Image(const string& Filename) {
2936 string Command;
2937
2938 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
2939
2940 Command = "simg2img '" + Filename + "' '" + Actual_Block_Device + "'";
Ethan Yonker96af84a2015-01-05 14:58:36 -06002941 LOGINFO("Flash command: '%s'\n", Command.c_str());
2942 TWFunc::Exec_Cmd(Command);
2943 return true;
2944}
2945
Ethan Yonker472f5062016-02-25 13:47:30 -06002946bool TWPartition::Flash_Image_FI(const string& Filename, ProgressTracking *progress) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002947 string Command;
Ethan Yonker472f5062016-02-25 13:47:30 -06002948 unsigned long long file_size;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002949
Ethan Yonker74db1572015-10-28 12:44:49 -05002950 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
Ethan Yonker472f5062016-02-25 13:47:30 -06002951 if (progress) {
2952 file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename));
2953 progress->SetPartitionSize(file_size);
2954 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002955 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
2956 Command = "erase_image " + MTD_Name;
2957 LOGINFO("Erase command: '%s'\n", Command.c_str());
2958 TWFunc::Exec_Cmd(Command);
2959 Command = "flash_image " + MTD_Name + " '" + Filename + "'";
2960 LOGINFO("Flash command: '%s'\n", Command.c_str());
2961 TWFunc::Exec_Cmd(Command);
Ethan Yonker472f5062016-02-25 13:47:30 -06002962 if (progress)
2963 progress->UpdateSize(file_size);
Ethan Yonker96af84a2015-01-05 14:58:36 -06002964 return true;
2965}
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05002966
2967void TWPartition::Change_Mount_Read_Only(bool new_value) {
2968 Mount_Read_Only = new_value;
2969}
2970
bigbiffce8f83c2015-12-12 18:30:21 -05002971bool TWPartition::Is_Read_Only() {
2972 return Mount_Read_Only;
2973}
2974
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05002975int TWPartition::Check_Lifetime_Writes() {
2976 bool original_read_only = Mount_Read_Only;
2977 int ret = 1;
2978
2979 Mount_Read_Only = true;
2980 if (Mount(false)) {
2981 Find_Actual_Block_Device();
2982 string block = basename(Actual_Block_Device.c_str());
2983 string file = "/sys/fs/" + Current_File_System + "/" + block + "/lifetime_write_kbytes";
2984 string result;
2985 if (TWFunc::Path_Exists(file)) {
2986 if (TWFunc::read_file(file, result) != 0) {
2987 LOGINFO("Check_Lifetime_Writes of '%s' failed to read_file\n", file.c_str());
2988 } else {
2989 LOGINFO("Check_Lifetime_Writes result: '%s'\n", result.c_str());
2990 if (result == "0") {
2991 ret = 0;
2992 }
2993 }
2994 } else {
2995 LOGINFO("Check_Lifetime_Writes file does not exist '%s'\n", file.c_str());
2996 }
2997 UnMount(true);
2998 } else {
2999 LOGINFO("Check_Lifetime_Writes failed to mount '%s'\n", Mount_Point.c_str());
3000 }
3001 Mount_Read_Only = original_read_only;
3002 return ret;
3003}
Ethan Yonker66a19492015-12-10 10:19:45 -06003004
3005int TWPartition::Decrypt_Adopted() {
3006#ifdef TW_INCLUDE_CRYPTO
3007 int ret = 1;
3008 Is_Adopted_Storage = false;
3009 string Adopted_Key_File = "";
3010
3011 if (!Removable)
3012 return ret;
3013
3014 int fd = open(Alternate_Block_Device.c_str(), O_RDONLY);
3015 if (fd < 0) {
3016 LOGINFO("failed to open '%s'\n", Alternate_Block_Device.c_str());
3017 return ret;
3018 }
3019 char type_guid[80];
3020 char part_guid[80];
3021
3022 if (gpt_disk_get_partition_info(fd, 2, type_guid, part_guid) == 0) {
3023 LOGINFO("type: '%s'\n", type_guid);
3024 LOGINFO("part: '%s'\n", part_guid);
3025 Adopted_GUID = part_guid;
3026 LOGINFO("Adopted_GUID '%s'\n", Adopted_GUID.c_str());
3027 if (strcmp(type_guid, TWGptAndroidExpand) == 0) {
3028 LOGINFO("android_expand found\n");
3029 Adopted_Key_File = "/data/misc/vold/expand_";
3030 Adopted_Key_File += part_guid;
3031 Adopted_Key_File += ".key";
3032 if (TWFunc::Path_Exists(Adopted_Key_File)) {
3033 Is_Adopted_Storage = true;
3034 /* Until we find a use case for this, I think it is safe
3035 * to disable USB Mass Storage whenever adopted storage
3036 * is present.
3037 */
3038 LOGINFO("Detected adopted storage, disabling USB mass storage mode\n");
3039 DataManager::SetValue("tw_has_usb_storage", 0);
3040 }
3041 }
3042 }
3043
3044 if (Is_Adopted_Storage) {
3045 string Adopted_Block_Device = Alternate_Block_Device + "p2";
3046 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
3047 Adopted_Block_Device = Alternate_Block_Device + "2";
3048 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
3049 LOGINFO("Adopted block device does not exist\n");
3050 goto exit;
3051 }
3052 }
3053 LOGINFO("key file is '%s', block device '%s'\n", Adopted_Key_File.c_str(), Adopted_Block_Device.c_str());
3054 char crypto_blkdev[MAXPATHLEN];
3055 std::string thekey;
3056 int fdkey = open(Adopted_Key_File.c_str(), O_RDONLY);
3057 if (fdkey < 0) {
3058 LOGINFO("failed to open key file\n");
3059 goto exit;
3060 }
3061 char buf[512];
3062 ssize_t n;
3063 while ((n = read(fdkey, &buf[0], sizeof(buf))) > 0) {
3064 thekey.append(buf, n);
3065 }
3066 close(fdkey);
3067 unsigned char* key = (unsigned char*) thekey.data();
3068 cryptfs_revert_ext_volume(part_guid);
3069
3070 ret = cryptfs_setup_ext_volume(part_guid, Adopted_Block_Device.c_str(), key, thekey.size(), crypto_blkdev);
3071 if (ret == 0) {
3072 LOGINFO("adopted storage new block device: '%s'\n", crypto_blkdev);
3073 Decrypted_Block_Device = crypto_blkdev;
3074 Is_Decrypted = true;
3075 Is_Encrypted = true;
3076 Find_Actual_Block_Device();
Kjell Braden3126a112016-06-19 16:58:15 +00003077 if (!Mount_Storage_Retry(false)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06003078 LOGERR("Failed to mount decrypted adopted storage device\n");
3079 Is_Decrypted = false;
3080 Is_Encrypted = false;
3081 cryptfs_revert_ext_volume(part_guid);
3082 ret = 1;
3083 } else {
Ethan Yonkerfcf3f242016-02-16 12:30:26 -06003084 UnMount(false);
3085 Has_Android_Secure = false;
3086 Symlink_Path = "";
3087 Symlink_Mount_Point = "";
3088 Backup_Name = Mount_Point.substr(1);
3089 Backup_Path = Mount_Point;
3090 TWPartition* sdext = PartitionManager.Find_Partition_By_Path("/sd-ext");
3091 if (sdext && sdext->Actual_Block_Device == Adopted_Block_Device) {
3092 LOGINFO("Removing /sd-ext from partition list due to adopted storage\n");
3093 PartitionManager.Remove_Partition_By_Path("/sd-ext");
3094 }
Ethan Yonker66a19492015-12-10 10:19:45 -06003095 Setup_Data_Media();
3096 Recreate_Media_Folder();
3097 Wipe_Available_in_GUI = true;
3098 Wipe_During_Factory_Reset = true;
3099 Can_Be_Backed_Up = true;
3100 Can_Encrypt_Backup = true;
3101 Use_Userdata_Encryption = true;
3102 Is_Storage = true;
3103 Storage_Name = "Adopted Storage";
3104 Is_SubPartition = true;
3105 SubPartition_Of = "/data";
3106 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
3107 DataManager::SetValue("tw_has_adopted_storage", 1);
3108 }
3109 } else {
3110 LOGERR("Failed to setup adopted storage decryption\n");
3111 }
3112 }
3113exit:
Matt Mower06543e32017-01-06 15:25:26 -06003114 close(fd);
Ethan Yonker66a19492015-12-10 10:19:45 -06003115 return ret;
3116#else
3117 LOGINFO("Decrypt_Adopted: no crypto support\n");
3118 return 1;
3119#endif
3120}
3121
3122void TWPartition::Revert_Adopted() {
3123#ifdef TW_INCLUDE_CRYPTO
3124 if (!Adopted_GUID.empty()) {
3125 PartitionManager.Remove_MTP_Storage(Mount_Point);
3126 UnMount(false);
3127 cryptfs_revert_ext_volume(Adopted_GUID.c_str());
3128 Is_Adopted_Storage = false;
3129 Is_Encrypted = false;
3130 Is_Decrypted = false;
3131 Decrypted_Block_Device = "";
3132 Find_Actual_Block_Device();
3133 Wipe_During_Factory_Reset = false;
3134 Can_Be_Backed_Up = false;
3135 Can_Encrypt_Backup = false;
3136 Use_Userdata_Encryption = false;
3137 Is_SubPartition = false;
3138 SubPartition_Of = "";
3139 Has_Data_Media = false;
3140 Storage_Path = Mount_Point;
3141 if (!Symlink_Mount_Point.empty()) {
3142 TWPartition* Dat = PartitionManager.Find_Partition_By_Path("/data");
3143 if (Dat) {
3144 Dat->UnMount(false);
3145 Dat->Symlink_Mount_Point = Symlink_Mount_Point;
3146 }
3147 Symlink_Mount_Point = "";
3148 }
3149 }
3150#else
3151 LOGINFO("Revert_Adopted: no crypto support\n");
3152#endif
3153}
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04003154
3155void TWPartition::Set_Backup_FileName(string fname) {
3156 Backup_FileName = fname;
3157}
3158
3159string TWPartition::Get_Backup_Name() {
3160 return Backup_Name;
3161}