blob: 543e8674b3644aaada3b6fd5035dfcd104b128e2 [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
54 #include "make_ext4fs.h"
55#endif
Ethan Yonker71413f42014-02-26 13:36:08 -060056
57#ifdef TW_INCLUDE_CRYPTO
Ethan Yonker253368a2014-11-25 15:00:52 -060058 #include "crypto/lollipop/cryptfs.h"
Ethan Yonker66a19492015-12-10 10:19:45 -060059 #include "gpt/gpt.h"
Ethan Yonkerbd7492d2016-12-07 13:55:01 -060060 #ifdef TW_INCLUDE_FBE
61 #include "crypto/ext4crypt/Decrypt.h"
Ethan Yonkerbd7492d2016-12-07 13:55:01 -060062 #endif
Ethan Yonkerbc85b632015-08-09 12:48:14 -050063#else
64 #define CRYPT_FOOTER_OFFSET 0x4000
Ethan Yonker71413f42014-02-26 13:36:08 -060065#endif
Dees_Troy5bf43922012-09-07 16:07:55 -040066}
Matt Mower87413642017-01-17 21:14:46 -060067#include <selinux/selinux.h>
Ethan Yonkerf27497f2014-02-09 11:48:33 -060068#include <selinux/label.h>
Dees Troy4159aed2014-02-28 17:24:43 +000069#ifdef HAVE_CAPABILITIES
70#include <sys/capability.h>
71#include <sys/xattr.h>
72#include <linux/xattr.h>
73#endif
HashBanged974bb2016-01-30 14:20:09 -050074#include <sparse_format.h>
Ethan Yonker472f5062016-02-25 13:47:30 -060075#include "progresstracking.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040076
bigbiff bigbiff9c754052013-01-09 09:09:08 -050077using namespace std;
78
Dees_Troya95f55c2013-08-17 13:14:43 +000079extern struct selabel_handle *selinux_handle;
Ethan Yonker6277c792014-09-15 14:54:30 -050080extern bool datamedia;
Dees_Troya95f55c2013-08-17 13:14:43 +000081
Hashcode62bd9e02013-11-19 21:59:42 -080082struct flag_list {
83 const char *name;
84 unsigned flag;
85};
86
Matt Mower4ab42b12016-04-21 13:52:18 -050087const struct flag_list mount_flags[] = {
Hashcode62bd9e02013-11-19 21:59:42 -080088 { "noatime", MS_NOATIME },
89 { "noexec", MS_NOEXEC },
90 { "nosuid", MS_NOSUID },
91 { "nodev", MS_NODEV },
92 { "nodiratime", MS_NODIRATIME },
93 { "ro", MS_RDONLY },
94 { "rw", 0 },
95 { "remount", MS_REMOUNT },
96 { "bind", MS_BIND },
97 { "rec", MS_REC },
Dees Troyc4bc30e2014-02-03 15:04:19 +000098#ifdef MS_UNBINDABLE
Hashcode62bd9e02013-11-19 21:59:42 -080099 { "unbindable", MS_UNBINDABLE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000100#endif
101#ifdef MS_PRIVATE
Hashcode62bd9e02013-11-19 21:59:42 -0800102 { "private", MS_PRIVATE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000103#endif
104#ifdef MS_SLAVE
Hashcode62bd9e02013-11-19 21:59:42 -0800105 { "slave", MS_SLAVE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000106#endif
107#ifdef MS_SHARED
Hashcode62bd9e02013-11-19 21:59:42 -0800108 { "shared", MS_SHARED },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000109#endif
Hashcode62bd9e02013-11-19 21:59:42 -0800110 { "sync", MS_SYNCHRONOUS },
111 { "defaults", 0 },
112 { 0, 0 },
113};
114
Matt Mower2416a502016-04-12 19:54:46 -0500115enum TW_FSTAB_FLAGS {
116 TWFLAG_DEFAULTS, // Retain position
117 TWFLAG_ANDSEC,
118 TWFLAG_BACKUP,
119 TWFLAG_BACKUPNAME,
120 TWFLAG_BLOCKSIZE,
121 TWFLAG_CANBEWIPED,
122 TWFLAG_CANENCRYPTBACKUP,
123 TWFLAG_DISPLAY,
124 TWFLAG_ENCRYPTABLE,
125 TWFLAG_FLASHIMG,
126 TWFLAG_FORCEENCRYPT,
127 TWFLAG_FSFLAGS,
128 TWFLAG_IGNOREBLKID,
129 TWFLAG_LENGTH,
130 TWFLAG_MOUNTTODECRYPT,
131 TWFLAG_REMOVABLE,
132 TWFLAG_RETAINLAYOUTVERSION,
133 TWFLAG_SETTINGSSTORAGE,
134 TWFLAG_STORAGE,
135 TWFLAG_STORAGENAME,
136 TWFLAG_SUBPARTITIONOF,
137 TWFLAG_SYMLINK,
138 TWFLAG_USERDATAENCRYPTBACKUP,
139 TWFLAG_USERMRF,
140 TWFLAG_WIPEDURINGFACTORYRESET,
141 TWFLAG_WIPEINGUI,
Ethan Yonker1b190162016-12-05 15:25:19 -0600142 TWFLAG_SLOTSELECT,
Matt Mower2416a502016-04-12 19:54:46 -0500143};
144
145/* Flags without a trailing '=' are considered dual format flags and can be
146 * written as either 'flagname' or 'flagname=', where the character following
147 * the '=' is Y,y,1 for true and false otherwise.
148 */
149const struct flag_list tw_flags[] = {
150 { "andsec", TWFLAG_ANDSEC },
151 { "backup", TWFLAG_BACKUP },
152 { "backupname=", TWFLAG_BACKUPNAME },
153 { "blocksize=", TWFLAG_BLOCKSIZE },
154 { "canbewiped", TWFLAG_CANBEWIPED },
155 { "canencryptbackup", TWFLAG_CANENCRYPTBACKUP },
156 { "defaults", TWFLAG_DEFAULTS },
157 { "display=", TWFLAG_DISPLAY },
158 { "encryptable=", TWFLAG_ENCRYPTABLE },
159 { "flashimg", TWFLAG_FLASHIMG },
160 { "forceencrypt=", TWFLAG_FORCEENCRYPT },
161 { "fsflags=", TWFLAG_FSFLAGS },
162 { "ignoreblkid", TWFLAG_IGNOREBLKID },
163 { "length=", TWFLAG_LENGTH },
164 { "mounttodecrypt", TWFLAG_MOUNTTODECRYPT },
165 { "removable", TWFLAG_REMOVABLE },
166 { "retainlayoutversion", TWFLAG_RETAINLAYOUTVERSION },
167 { "settingsstorage", TWFLAG_SETTINGSSTORAGE },
168 { "storage", TWFLAG_STORAGE },
169 { "storagename=", TWFLAG_STORAGENAME },
170 { "subpartitionof=", TWFLAG_SUBPARTITIONOF },
171 { "symlink=", TWFLAG_SYMLINK },
172 { "userdataencryptbackup", TWFLAG_USERDATAENCRYPTBACKUP },
173 { "usermrf", TWFLAG_USERMRF },
174 { "wipeduringfactoryreset", TWFLAG_WIPEDURINGFACTORYRESET },
175 { "wipeingui", TWFLAG_WIPEINGUI },
Ethan Yonker1b190162016-12-05 15:25:19 -0600176 { "slotselect", TWFLAG_SLOTSELECT },
Matt Mower2416a502016-04-12 19:54:46 -0500177 { 0, 0 },
178};
179
that9e0593e2014-10-08 00:01:24 +0200180TWPartition::TWPartition() {
Dees_Troy51a0e822012-09-05 15:24:24 -0400181 Can_Be_Mounted = false;
182 Can_Be_Wiped = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500183 Can_Be_Backed_Up = false;
Vojtech Bocek1dc30982013-08-30 21:49:30 +0200184 Use_Rm_Rf = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400185 Wipe_During_Factory_Reset = false;
186 Wipe_Available_in_GUI = false;
187 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -0400188 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400189 SubPartition_Of = "";
190 Symlink_Path = "";
191 Symlink_Mount_Point = "";
192 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -0400193 Backup_Path = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400194 Actual_Block_Device = "";
195 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400196 Alternate_Block_Device = "";
197 Removable = false;
198 Is_Present = false;
199 Length = 0;
200 Size = 0;
201 Used = 0;
202 Free = 0;
203 Backup_Size = 0;
204 Can_Be_Encrypted = false;
205 Is_Encrypted = false;
206 Is_Decrypted = false;
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600207 Is_FBE = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600208 Mount_To_Decrypt = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400209 Decrypted_Block_Device = "";
210 Display_Name = "";
Dees_Troya13d74f2013-03-24 08:54:55 -0500211 Backup_Display_Name = "";
212 Storage_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400213 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -0400214 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400215 MTD_Name = "";
bigbiffce8f83c2015-12-12 18:30:21 -0500216 Backup_Method = BM_NONE;
Dees_Troy83bd4832013-05-04 12:39:56 +0000217 Can_Encrypt_Backup = false;
218 Use_Userdata_Encryption = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400219 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -0400220 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400221 Is_Storage = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500222 Is_Settings_Storage = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400223 Storage_Path = "";
224 Current_File_System = "";
225 Fstab_File_System = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800226 Mount_Flags = 0;
227 Mount_Options = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400228 Format_Block_Size = 0;
Dees_Troy68cab492012-12-12 19:29:35 +0000229 Ignore_Blkid = false;
Dees_Troy16c2b312013-01-15 16:51:18 +0000230 Retain_Layout_Version = false;
Ethan Yonker253368a2014-11-25 15:00:52 -0600231 Crypto_Key_Location = "footer";
Ethan Yonker726a0202014-12-16 20:01:38 -0600232 MTP_Storage_ID = 0;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600233 Can_Flash_Img = false;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500234 Mount_Read_Only = false;
Ethan Yonker66a19492015-12-10 10:19:45 -0600235 Is_Adopted_Storage = false;
236 Adopted_GUID = "";
Ethan Yonker1b190162016-12-05 15:25:19 -0600237 SlotSelect = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400238}
239
240TWPartition::~TWPartition(void) {
241 // Do nothing
242}
243
Matt Mower2b2dd152016-04-26 11:24:08 -0500244bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error) {
245 char full_line[MAX_FSTAB_LINE_LENGTH];
Matt Mower2416a502016-04-12 19:54:46 -0500246 char twflags[MAX_FSTAB_LINE_LENGTH] = "";
Dees_Troy5bf43922012-09-07 16:07:55 -0400247 char* ptr;
Matt Mower2b2dd152016-04-26 11:24:08 -0500248 int line_len = strlen(fstab_line), index = 0, item_index = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500249 bool skip = false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400250
Matt Mower2b2dd152016-04-26 11:24:08 -0500251 strlcpy(full_line, fstab_line, sizeof(full_line));
Dees_Troy51127312012-09-08 13:08:49 -0400252 for (index = 0; index < line_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500253 if (full_line[index] == 34)
254 skip = !skip;
255 if (!skip && full_line[index] <= 32)
Dees_Troy5bf43922012-09-07 16:07:55 -0400256 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400257 }
Dees_Troy7c2dec82012-09-26 09:49:14 -0400258 Mount_Point = full_line;
Dees_Troy2673cec2013-04-02 20:22:16 +0000259 LOGINFO("Processing '%s'\n", Mount_Point.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -0400260 Backup_Path = Mount_Point;
Dees_Troya13d74f2013-03-24 08:54:55 -0500261 Storage_Path = Mount_Point;
Dees_Troy70737fa2013-04-08 13:19:20 +0000262 Display_Name = full_line + 1;
263 Backup_Display_Name = Display_Name;
264 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400265 index = Mount_Point.size();
266 while (index < line_len) {
267 while (index < line_len && full_line[index] == '\0')
268 index++;
269 if (index >= line_len)
270 continue;
271 ptr = full_line + index;
272 if (item_index == 0) {
273 // File System
274 Fstab_File_System = ptr;
275 Current_File_System = ptr;
276 item_index++;
277 } else if (item_index == 1) {
278 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400279 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
Dees_Troy094207a2012-09-26 12:00:39 -0400280 MTD_Name = ptr;
281 Find_MTD_Block_Device(MTD_Name);
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400282 } else if (Fstab_File_System == "bml") {
283 if (Mount_Point == "/boot")
284 MTD_Name = "boot";
285 else if (Mount_Point == "/recovery")
286 MTD_Name = "recovery";
287 Primary_Block_Device = ptr;
288 if (*ptr != '/')
Dees_Troy2673cec2013-04-02 20:22:16 +0000289 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 -0400290 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400291 if (Display_Error)
Matt Mower2b2dd152016-04-26 11:24:08 -0500292 LOGERR("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
Dees_Troy5bf43922012-09-07 16:07:55 -0400293 else
Matt Mower2b2dd152016-04-26 11:24:08 -0500294 LOGINFO("Invalid block device '%s' in fstab line '%s'", ptr, fstab_line);
Matt Mower72c87ce2016-04-26 14:34:56 -0500295 return false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400296 } else {
297 Primary_Block_Device = ptr;
298 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400299 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400300 item_index++;
301 } else if (item_index > 1) {
302 if (*ptr == '/') {
303 // Alternate Block Device
304 Alternate_Block_Device = ptr;
305 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
306 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
307 // Partition length
308 ptr += 7;
309 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400310 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
311 // Custom flags, save for later so that new values aren't overwritten by defaults
312 ptr += 6;
Matt Mower2416a502016-04-12 19:54:46 -0500313 strlcpy(twflags, ptr, sizeof(twflags));
Dees_Troy38bd7602012-09-14 13:33:53 -0400314 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
315 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400316 } else {
317 // Unhandled data
Matt Mower2b2dd152016-04-26 11:24:08 -0500318 LOGINFO("Unhandled fstab information '%s' in fstab line '%s'\n", ptr, fstab_line);
Dees_Troy5bf43922012-09-07 16:07:55 -0400319 }
320 }
321 while (index < line_len && full_line[index] != '\0')
322 index++;
323 }
324
325 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
326 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000327 LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400328 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000329 LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Matt Mower72c87ce2016-04-26 14:34:56 -0500330 return false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400331 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400332 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400333 Setup_File_System(Display_Error);
334 if (Mount_Point == "/system") {
335 Display_Name = "System";
Dees_Troya13d74f2013-03-24 08:54:55 -0500336 Backup_Display_Name = Display_Name;
337 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400338 Wipe_Available_in_GUI = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500339 Can_Be_Backed_Up = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500340 Mount_Read_Only = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400341 } else if (Mount_Point == "/data") {
342 Display_Name = "Data";
Dees_Troya13d74f2013-03-24 08:54:55 -0500343 Backup_Display_Name = Display_Name;
344 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400345 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400346 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500347 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000348 Can_Encrypt_Backup = true;
349 Use_Userdata_Encryption = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400350 } else if (Mount_Point == "/cache") {
351 Display_Name = "Cache";
Dees_Troya13d74f2013-03-24 08:54:55 -0500352 Backup_Display_Name = Display_Name;
353 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400354 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400355 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500356 Can_Be_Backed_Up = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400357 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400358 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400359 Display_Name = "DataData";
Dees_Troya13d74f2013-03-24 08:54:55 -0500360 Backup_Display_Name = Display_Name;
361 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400362 Is_SubPartition = true;
363 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400364 DataManager::SetValue(TW_HAS_DATADATA, 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500365 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000366 Can_Encrypt_Backup = true;
367 Use_Userdata_Encryption = false; // This whole partition should be encrypted
Dees_Troy5bf43922012-09-07 16:07:55 -0400368 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400369 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400370 Display_Name = "SD-Ext";
Dees_Troya13d74f2013-03-24 08:54:55 -0500371 Backup_Display_Name = Display_Name;
372 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400373 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400374 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500375 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000376 Can_Encrypt_Backup = true;
377 Use_Userdata_Encryption = true;
Dees_Troy2c50e182012-09-26 20:05:28 -0400378 } else if (Mount_Point == "/boot") {
379 Display_Name = "Boot";
Dees_Troya13d74f2013-03-24 08:54:55 -0500380 Backup_Display_Name = Display_Name;
Dees_Troy2c50e182012-09-26 20:05:28 -0400381 DataManager::SetValue("tw_boot_is_mountable", 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500382 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500383 } else if (Mount_Point == "/vendor") {
384 Display_Name = "Vendor";
385 Backup_Display_Name = Display_Name;
386 Storage_Name = Display_Name;
387 Mount_Read_Only = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400388 }
389#ifdef TW_EXTERNAL_STORAGE_PATH
390 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
391 Is_Storage = true;
392 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
Dees_Troyc51f1f92012-09-20 15:32:13 -0400393 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500394 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400395#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000396 if (Mount_Point == "/sdcard" || Mount_Point == "/external_sd" || Mount_Point == "/external_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400397 Is_Storage = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400398 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500399 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400400#endif
Dees_Troyb05ddee2013-01-28 20:24:50 +0000401 }
Dees_Troy8170a922012-09-18 15:40:25 -0400402#ifdef TW_INTERNAL_STORAGE_PATH
403 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
404 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500405 Is_Settings_Storage = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400406 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troya13d74f2013-03-24 08:54:55 -0500407 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400408 }
409#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000410 if (Mount_Point == "/emmc" || Mount_Point == "/internal_sd" || Mount_Point == "/internal_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400411 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500412 Is_Settings_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500413 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400414 }
415#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400416 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400417 Find_Actual_Block_Device();
Ethan Yonker1b190162016-12-05 15:25:19 -0600418 Setup_Image();
Dees_Troya13d74f2013-03-24 08:54:55 -0500419 if (Mount_Point == "/boot") {
420 Display_Name = "Boot";
421 Backup_Display_Name = Display_Name;
422 Can_Be_Backed_Up = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600423 Can_Flash_Img = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500424 } else if (Mount_Point == "/recovery") {
425 Display_Name = "Recovery";
426 Backup_Display_Name = Display_Name;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600427 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500428 } else if (Mount_Point == "/system_image") {
429 Display_Name = "System Image";
430 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500431 Can_Flash_Img = true;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -0500432 Can_Be_Backed_Up = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500433 } else if (Mount_Point == "/vendor_image") {
434 Display_Name = "Vendor Image";
435 Backup_Display_Name = Display_Name;
HashBanged974bb2016-01-30 14:20:09 -0500436 Can_Flash_Img = true;
Ethan Yonker1673e3d2015-10-26 21:51:58 -0500437 Can_Be_Backed_Up = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500438 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400439 }
440
Matt Mower2416a502016-04-12 19:54:46 -0500441 // Process TWRP fstab flags
442 if (strlen(twflags) > 0) {
443 string Prev_Display_Name = Display_Name;
444 string Prev_Storage_Name = Storage_Name;
445 string Prev_Backup_Display_Name = Backup_Display_Name;
446 Display_Name = "";
447 Storage_Name = "";
448 Backup_Display_Name = "";
449
450 Process_TW_Flags(twflags, Display_Error);
451
452 bool has_display_name = !Display_Name.empty();
453 bool has_storage_name = !Storage_Name.empty();
454 bool has_backup_name = !Backup_Display_Name.empty();
455 if (!has_display_name) Display_Name = Prev_Display_Name;
456 if (!has_storage_name) Storage_Name = Prev_Storage_Name;
457 if (!has_backup_name) Backup_Display_Name = Prev_Backup_Display_Name;
458
459 if (has_display_name && !has_storage_name)
460 Storage_Name = Display_Name;
461 if (!has_display_name && has_storage_name)
462 Display_Name = Storage_Name;
463 if (has_display_name && !has_backup_name && Backup_Display_Name != "Android Secure")
464 Backup_Display_Name = Display_Name;
465 if (!has_display_name && has_backup_name)
466 Display_Name = Backup_Display_Name;
467 }
Dees_Troy51127312012-09-08 13:08:49 -0400468 return true;
469}
470
Matt Mower72c87ce2016-04-26 14:34:56 -0500471void TWPartition::Partition_Post_Processing(bool Display_Error) {
472 if (Mount_Point == "/data")
473 Setup_Data_Partition(Display_Error);
474 else if (Mount_Point == "/cache")
475 Setup_Cache_Partition(Display_Error);
476}
477
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600478void TWPartition::ExcludeAll(const string& path) {
479 backup_exclusions.add_absolute_dir(path);
480 wipe_exclusions.add_absolute_dir(path);
481}
482
Matt Mower72c87ce2016-04-26 14:34:56 -0500483void TWPartition::Setup_Data_Partition(bool Display_Error) {
484 if (Mount_Point != "/data")
485 return;
486
487 // Ensure /data is not mounted as tmpfs for qcom hardware decrypt
488 UnMount(false);
489
490#ifdef TW_INCLUDE_CRYPTO
491 if (datamedia)
492 Setup_Data_Media();
493 Can_Be_Encrypted = true;
494 char crypto_blkdev[255];
495 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
496 if (strcmp(crypto_blkdev, "error") != 0) {
497 DataManager::SetValue(TW_IS_DECRYPTED, 1);
498 Is_Encrypted = true;
499 Is_Decrypted = true;
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600500 Is_FBE = false;
501 DataManager::SetValue(TW_IS_FBE, 0);
Matt Mower72c87ce2016-04-26 14:34:56 -0500502 Decrypted_Block_Device = crypto_blkdev;
503 LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
504 } else if (!Mount(false)) {
505 if (Is_Present) {
506 set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
507 if (cryptfs_check_footer() == 0) {
508 Is_Encrypted = true;
509 Is_Decrypted = false;
510 Can_Be_Mounted = false;
511 Current_File_System = "emmc";
Ethan Yonker1b190162016-12-05 15:25:19 -0600512 Setup_Image();
Matt Mower72c87ce2016-04-26 14:34:56 -0500513 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
514 DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
515 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
516 DataManager::SetValue("tw_crypto_display", "");
517 } else {
518 gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
519 }
520 } else {
521 LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
522 }
523 } else {
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600524 if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
525 LOGINFO("File Based Encryption is present\n");
526#ifdef TW_INCLUDE_FBE
527 ExcludeAll(Mount_Point + "/convert_fbe");
528 ExcludeAll(Mount_Point + "/unencrypted");
529 //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
530 ExcludeAll(Mount_Point + "/misc/vold/user_keys");
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600531 //ExcludeAll(Mount_Point + "/system_ce");
532 //ExcludeAll(Mount_Point + "/system_de");
533 //ExcludeAll(Mount_Point + "/misc_ce");
534 //ExcludeAll(Mount_Point + "/misc_de");
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600535 ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
536 ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
537 ExcludeAll(Mount_Point + "/system/locksettings.db");
538 //ExcludeAll(Mount_Point + "/system/locksettings.db-shm"); // don't seem to need this one, but the other 2 are needed
539 ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600540 //ExcludeAll(Mount_Point + "/user_de");
Ethan Yonkerbd7492d2016-12-07 13:55:01 -0600541 //ExcludeAll(Mount_Point + "/misc/profiles/cur/0"); // might be important later
542 ExcludeAll(Mount_Point + "/misc/gatekeeper");
543 ExcludeAll(Mount_Point + "/drm/kek.dat");
544 int retry_count = 3;
545 while (!Decrypt_DE() && --retry_count)
546 usleep(2000);
547 if (retry_count > 0) {
548 property_set("ro.crypto.state", "encrypted");
549 Is_Encrypted = true;
550 Is_Decrypted = false;
551 Is_FBE = true;
552 DataManager::SetValue(TW_IS_FBE, 1);
553 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
554 string filename;
555 DataManager::SetValue(TW_CRYPTO_PWTYPE, Get_Password_Type(0, filename));
556 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
557 DataManager::SetValue("tw_crypto_display", "");
558 }
559#else
560 LOGERR("FBE found but FBE support not present in TWRP\n");
561#endif
562 } else {
563 // Filesystem is not encrypted and the mount succeeded, so return to
564 // the original unmounted state
565 UnMount(false);
566 }
Matt Mower72c87ce2016-04-26 14:34:56 -0500567 }
568 if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
569 Setup_Data_Media();
570 Recreate_Media_Folder();
571 }
572#else
573 if (datamedia) {
574 Setup_Data_Media();
575 Recreate_Media_Folder();
576 }
577#endif
578}
579
580void TWPartition::Setup_Cache_Partition(bool Display_Error __unused) {
581 if (Mount_Point != "/cache")
582 return;
583
584 if (!Mount(true))
585 return;
586
587 if (!TWFunc::Path_Exists("/cache/recovery/.")) {
588 LOGINFO("Recreating /cache/recovery folder\n");
589 if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
590 LOGERR("Could not create /cache/recovery\n");
591 }
592}
593
Matt Mower4ab42b12016-04-21 13:52:18 -0500594void TWPartition::Process_FS_Flags(const char *str) {
595 char *options = strdup(str);
596 char *ptr, *savep;
Hashcode62bd9e02013-11-19 21:59:42 -0800597
Matt Mower4ab42b12016-04-21 13:52:18 -0500598 Mount_Options = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800599
Matt Mower4ab42b12016-04-21 13:52:18 -0500600 // Avoid issues with potentially nested strtok by using strtok_r
601 ptr = strtok_r(options, ",", &savep);
602 while (ptr) {
603 const struct flag_list* mount_flag = mount_flags;
604
605 for (; mount_flag->name; mount_flag++) {
606 // mount_flags are never postfixed by '=',
607 // so only match identical strings (including length)
608 if (strcmp(ptr, mount_flag->name) == 0) {
609 Mount_Flags |= mount_flag->flag;
Hashcode62bd9e02013-11-19 21:59:42 -0800610 break;
611 }
612 }
613
Matt Mower4ab42b12016-04-21 13:52:18 -0500614 if (mount_flag->flag == MS_RDONLY)
615 Mount_Read_Only = true;
Hashcode62bd9e02013-11-19 21:59:42 -0800616
Matt Mower4ab42b12016-04-21 13:52:18 -0500617 if (mount_flag->name != 0) {
618 if (!Mount_Options.empty())
619 Mount_Options += ",";
620 Mount_Options += mount_flag->name;
621 } else {
622 LOGINFO("Unhandled mount flag: '%s'\n", ptr);
623 }
624
625 ptr = strtok_r(NULL, ",", &savep);
626 }
627 free(options);
Hashcode62bd9e02013-11-19 21:59:42 -0800628}
629
Matt Mower2416a502016-04-12 19:54:46 -0500630void TWPartition::Apply_TW_Flag(const unsigned flag, const char* str, const bool val) {
631 switch (flag) {
632 case TWFLAG_ANDSEC:
633 Has_Android_Secure = val;
634 break;
635 case TWFLAG_BACKUP:
636 Can_Be_Backed_Up = val;
637 break;
638 case TWFLAG_BACKUPNAME:
639 Backup_Display_Name = str;
640 break;
641 case TWFLAG_BLOCKSIZE:
642 Format_Block_Size = (unsigned long)(atol(str));
643 break;
644 case TWFLAG_CANBEWIPED:
645 Can_Be_Wiped = val;
646 break;
647 case TWFLAG_CANENCRYPTBACKUP:
648 Can_Encrypt_Backup = val;
649 break;
650 case TWFLAG_DEFAULTS:
651 // Do nothing
652 break;
653 case TWFLAG_DISPLAY:
654 Display_Name = str;
655 break;
656 case TWFLAG_ENCRYPTABLE:
657 case TWFLAG_FORCEENCRYPT:
658 Crypto_Key_Location = str;
659 break;
660 case TWFLAG_FLASHIMG:
661 Can_Flash_Img = val;
662 break;
663 case TWFLAG_FSFLAGS:
Matt Mower4ab42b12016-04-21 13:52:18 -0500664 Process_FS_Flags(str);
Matt Mower2416a502016-04-12 19:54:46 -0500665 break;
666 case TWFLAG_IGNOREBLKID:
667 Ignore_Blkid = val;
668 break;
669 case TWFLAG_LENGTH:
670 Length = atoi(str);
671 break;
672 case TWFLAG_MOUNTTODECRYPT:
673 Mount_To_Decrypt = val;
674 break;
675 case TWFLAG_REMOVABLE:
676 Removable = val;
677 break;
678 case TWFLAG_RETAINLAYOUTVERSION:
679 Retain_Layout_Version = val;
680 break;
681 case TWFLAG_SETTINGSSTORAGE:
682 Is_Settings_Storage = val;
683 if (Is_Settings_Storage)
684 Is_Storage = true;
685 break;
686 case TWFLAG_STORAGE:
687 Is_Storage = val;
688 break;
689 case TWFLAG_STORAGENAME:
690 Storage_Name = str;
691 break;
692 case TWFLAG_SUBPARTITIONOF:
693 Is_SubPartition = true;
694 SubPartition_Of = str;
695 break;
696 case TWFLAG_SYMLINK:
697 Symlink_Path = str;
698 break;
699 case TWFLAG_USERDATAENCRYPTBACKUP:
700 Use_Userdata_Encryption = val;
701 if (Use_Userdata_Encryption)
702 Can_Encrypt_Backup = true;
703 break;
704 case TWFLAG_USERMRF:
705 Use_Rm_Rf = val;
706 break;
707 case TWFLAG_WIPEDURINGFACTORYRESET:
708 Wipe_During_Factory_Reset = val;
709 if (Wipe_During_Factory_Reset) {
710 Can_Be_Wiped = true;
711 Wipe_Available_in_GUI = true;
712 }
713 break;
714 case TWFLAG_WIPEINGUI:
715 Wipe_Available_in_GUI = val;
716 if (Wipe_Available_in_GUI)
717 Can_Be_Wiped = true;
718 break;
Ethan Yonker1b190162016-12-05 15:25:19 -0600719 case TWFLAG_SLOTSELECT:
720 SlotSelect = true;
721 break;
Matt Mower2416a502016-04-12 19:54:46 -0500722 default:
723 // Should not get here
724 LOGINFO("Flag identified for processing, but later unmatched: %i\n", flag);
725 break;
726 }
727}
Dees_Troy51127312012-09-08 13:08:49 -0400728
Matt Mower2416a502016-04-12 19:54:46 -0500729void TWPartition::Process_TW_Flags(char *flags, bool Display_Error) {
730 char separator[2] = {'\n', 0};
731 char *ptr, *savep;
732
733 // Semicolons within double-quotes are not forbidden, so replace
734 // only the semicolons intended as separators with '\n' for strtok
735 for (unsigned i = 0, skip = 0; i < strlen(flags); i++) {
736 if (flags[i] == '\"')
Dees_Troya13d74f2013-03-24 08:54:55 -0500737 skip = !skip;
Matt Mower2416a502016-04-12 19:54:46 -0500738 if (!skip && flags[i] == ';')
739 flags[i] = separator[0];
Dees_Troy51127312012-09-08 13:08:49 -0400740 }
741
Matt Mower2416a502016-04-12 19:54:46 -0500742 // Avoid issues with potentially nested strtok by using strtok_r
743 ptr = strtok_r(flags, separator, &savep);
744 while (ptr) {
745 int ptr_len = strlen(ptr);
746 const struct flag_list* tw_flag = tw_flags;
Hashcode62bd9e02013-11-19 21:59:42 -0800747
Matt Mower2416a502016-04-12 19:54:46 -0500748 for (; tw_flag->name; tw_flag++) {
749 int flag_len = strlen(tw_flag->name);
750
751 if (strncmp(ptr, tw_flag->name, flag_len) == 0) {
752 bool flag_val = false;
753
754 if (ptr_len > flag_len && (tw_flag->name)[flag_len-1] != '='
755 && ptr[flag_len] != '=') {
756 // Handle flags with same starting string
757 // (e.g. backup and backupname)
758 continue;
759 } else if (ptr_len > flag_len && ptr[flag_len] == '=') {
760 // Handle flags with dual format: Part 1
761 // (e.g. backup and backup=y. backup=y handled here)
762 ptr += flag_len + 1;
763 TWFunc::Strip_Quotes(ptr);
764 // Skip flags with empty argument
765 // (e.g. backup=)
766 if (strlen(ptr) == 0) {
767 LOGINFO("Flag missing argument or should not include '=': %s=\n", tw_flag->name);
768 break;
769 }
770 flag_val = strchr("yY1", *ptr) != NULL;
771 } else if (ptr_len == flag_len
772 && (tw_flag->name)[flag_len-1] == '=') {
773 // Skip flags missing argument after =
774 // (e.g. backupname=)
775 LOGINFO("Flag missing argument: %s\n", tw_flag->name);
776 break;
777 } else if (ptr_len > flag_len
778 && (tw_flag->name)[flag_len-1] == '=') {
779 // Handle arguments to flags
780 // (e.g. backupname="My Stuff")
781 ptr += flag_len;
782 TWFunc::Strip_Quotes(ptr);
783 // Skip flags with empty argument
784 // (e.g. backupname="")
785 if (strlen(ptr) == 0) {
786 LOGINFO("Flag missing argument: %s\n", tw_flag->name);
787 break;
788 }
789 } else if (ptr_len == flag_len) {
790 // Handle flags with dual format: Part 2
791 // (e.g. backup and backup=y. backup handled here)
792 flag_val = true;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600793 } else {
Matt Mower2416a502016-04-12 19:54:46 -0500794 LOGINFO("Flag matched, but could not be processed: %s\n", ptr);
795 break;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600796 }
Matt Mower2416a502016-04-12 19:54:46 -0500797
798 Apply_TW_Flag(tw_flag->flag, ptr, flag_val);
799 break;
Ethan Yonker96af84a2015-01-05 14:58:36 -0600800 }
Matt Mower2416a502016-04-12 19:54:46 -0500801 }
802 if (tw_flag->name == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400803 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000804 LOGERR("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400805 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000806 LOGINFO("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400807 }
Matt Mower2416a502016-04-12 19:54:46 -0500808 ptr = strtok_r(NULL, separator, &savep);
Dees_Troy51127312012-09-08 13:08:49 -0400809 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400810}
811
Dees_Troy5bf43922012-09-07 16:07:55 -0400812bool TWPartition::Is_File_System(string File_System) {
813 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400814 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400815 File_System == "ext4" ||
816 File_System == "vfat" ||
817 File_System == "ntfs" ||
818 File_System == "yaffs2" ||
bigbiff bigbiff3e146522012-11-14 14:32:59 -0500819 File_System == "exfat" ||
Dees_Troye5017042013-08-29 16:38:55 +0000820 File_System == "f2fs" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400821 File_System == "auto")
822 return true;
823 else
824 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400825}
826
Dees_Troy5bf43922012-09-07 16:07:55 -0400827bool TWPartition::Is_Image(string File_System) {
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400828 if (File_System == "emmc" || File_System == "mtd" || File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400829 return true;
830 else
831 return false;
832}
833
Dees_Troy51127312012-09-08 13:08:49 -0400834bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Ethan Yonker93ac7a02016-11-07 22:05:58 -0600835 if (TWFunc::Get_D_Type_From_Stat(Path) != S_IFDIR)
836 unlink(Path.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400837 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400838 if (mkdir(Path.c_str(), 0777) == -1) {
839 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -0500840 gui_msg(Msg(msg::kError, "create_folder_strerr=Can not create '{1}' folder ({2}).")(Path)(strerror(errno)));
Dees_Troy51127312012-09-08 13:08:49 -0400841 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000842 LOGINFO("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400843 return false;
844 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000845 LOGINFO("Created '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400846 return true;
847 }
848 }
849 return true;
850}
851
Dees_Troy5bf43922012-09-07 16:07:55 -0400852void TWPartition::Setup_File_System(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400853 Can_Be_Mounted = true;
854 Can_Be_Wiped = true;
855
Dees_Troy5bf43922012-09-07 16:07:55 -0400856 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400857 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400858 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
859 Backup_Name = Display_Name;
bigbiffce8f83c2015-12-12 18:30:21 -0500860 Backup_Method = BM_FILES;
Dees_Troy5bf43922012-09-07 16:07:55 -0400861}
862
Ethan Yonker1b190162016-12-05 15:25:19 -0600863void TWPartition::Setup_Image() {
Dees_Troy5bf43922012-09-07 16:07:55 -0400864 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
865 Backup_Name = Display_Name;
Gary Peck82599a82012-11-21 16:23:12 -0800866 if (Current_File_System == "emmc")
bigbiffce8f83c2015-12-12 18:30:21 -0500867 Backup_Method = BM_DD;
Gary Peck82599a82012-11-21 16:23:12 -0800868 else if (Current_File_System == "mtd" || Current_File_System == "bml")
bigbiffce8f83c2015-12-12 18:30:21 -0500869 Backup_Method = BM_FLASH_UTILS;
Dees_Troy5bf43922012-09-07 16:07:55 -0400870 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000871 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 -0400872}
873
Dees_Troye58d5262012-09-21 12:27:57 -0400874void TWPartition::Setup_AndSec(void) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500875 Backup_Display_Name = "Android Secure";
Dees_Troye58d5262012-09-21 12:27:57 -0400876 Backup_Name = "and-sec";
Dees_Troya13d74f2013-03-24 08:54:55 -0500877 Can_Be_Backed_Up = true;
Dees_Troye58d5262012-09-21 12:27:57 -0400878 Has_Android_Secure = true;
879 Symlink_Path = Mount_Point + "/.android_secure";
880 Symlink_Mount_Point = "/and-sec";
881 Backup_Path = Symlink_Mount_Point;
882 Make_Dir("/and-sec", true);
883 Recreate_AndSec_Folder();
Kjell Braden3126a112016-06-19 16:58:15 +0000884 Mount_Storage_Retry(true);
Dees_Troye58d5262012-09-21 12:27:57 -0400885}
886
that9e0593e2014-10-08 00:01:24 +0200887void TWPartition::Setup_Data_Media() {
Ethan Yonker6277c792014-09-15 14:54:30 -0500888 LOGINFO("Setting up '%s' as data/media emulated storage.\n", Mount_Point.c_str());
Ethan Yonker66a19492015-12-10 10:19:45 -0600889 if (Storage_Name.empty() || Storage_Name == "Data")
890 Storage_Name = "Internal Storage";
Ethan Yonker6277c792014-09-15 14:54:30 -0500891 Has_Data_Media = true;
892 Is_Storage = true;
Ethan Yonker66a19492015-12-10 10:19:45 -0600893 Storage_Path = Mount_Point + "/media";
Ethan Yonker6277c792014-09-15 14:54:30 -0500894 Symlink_Path = Storage_Path;
Ethan Yonker66a19492015-12-10 10:19:45 -0600895 if (Mount_Point == "/data") {
896 Is_Settings_Storage = true;
897 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
898 Make_Dir("/emmc", false);
899 Symlink_Mount_Point = "/emmc";
900 } else {
901 Make_Dir("/sdcard", false);
902 Symlink_Mount_Point = "/sdcard";
903 }
904 if (Mount(false) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
905 Storage_Path = Mount_Point + "/media/0";
906 Symlink_Path = Storage_Path;
907 DataManager::SetValue(TW_INTERNAL_PATH, Mount_Point + "/media/0");
908 UnMount(true);
909 }
910 DataManager::SetValue("tw_has_internal", 1);
911 DataManager::SetValue("tw_has_data_media", 1);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600912 backup_exclusions.add_absolute_dir("/data/data/com.google.android.music/files");
Ethan Yonker6355b562017-05-01 09:42:17 -0500913 wipe_exclusions.add_absolute_dir(Mount_Point + "/misc/vold"); // adopted storage keys
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600914 ExcludeAll(Mount_Point + "/.layout_version");
915 ExcludeAll(Mount_Point + "/system/storage.xml");
Ethan Yonker6277c792014-09-15 14:54:30 -0500916 } else {
Ethan Yonker66a19492015-12-10 10:19:45 -0600917 if (Mount(true) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
918 Storage_Path = Mount_Point + "/media/0";
919 Symlink_Path = Storage_Path;
920 UnMount(true);
921 }
Ethan Yonker6277c792014-09-15 14:54:30 -0500922 }
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600923 ExcludeAll(Mount_Point + "/media");
Ethan Yonker6277c792014-09-15 14:54:30 -0500924}
925
Dees_Troy5bf43922012-09-07 16:07:55 -0400926void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
927 char device[512], realDevice[512];
928
929 strcpy(device, Block.c_str());
930 memset(realDevice, 0, sizeof(realDevice));
931 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
932 {
933 strcpy(device, realDevice);
934 memset(realDevice, 0, sizeof(realDevice));
935 }
936
937 if (device[0] != '/') {
938 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000939 LOGERR("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400940 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000941 LOGINFO("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400942 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400943 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400944 Block = device;
945 return;
946 }
947}
948
Kjell Braden3126a112016-06-19 16:58:15 +0000949bool TWPartition::Mount_Storage_Retry(bool Display_Error) {
Dees_Troy8e337f32012-10-13 22:07:49 -0400950 // On some devices, storage doesn't want to mount right away, retry and sleep
Kjell Braden3126a112016-06-19 16:58:15 +0000951 if (!Mount(Display_Error)) {
Dees_Troy8e337f32012-10-13 22:07:49 -0400952 int retry_count = 5;
953 while (retry_count > 0 && !Mount(false)) {
954 usleep(500000);
955 retry_count--;
956 }
Kjell Braden3126a112016-06-19 16:58:15 +0000957 return Mount(Display_Error);
Dees_Troy8e337f32012-10-13 22:07:49 -0400958 }
Kjell Braden3126a112016-06-19 16:58:15 +0000959 return true;
Dees_Troy8e337f32012-10-13 22:07:49 -0400960}
961
Dees_Troy38bd7602012-09-14 13:33:53 -0400962bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
963 FILE *fp = NULL;
964 char line[255];
965
966 fp = fopen("/proc/mtd", "rt");
967 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000968 LOGERR("Device does not support /proc/mtd\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400969 return false;
970 }
971
972 while (fgets(line, sizeof(line), fp) != NULL)
973 {
974 char device[32], label[32];
975 unsigned long size = 0;
Dees_Troy38bd7602012-09-14 13:33:53 -0400976 int deviceId;
977
978 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
979
980 // Skip header and blank lines
981 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
982 continue;
983
984 // Strip off the trailing " from the label
985 label[strlen(label)-1] = '\0';
986
987 if (strcmp(label, MTD_Name.c_str()) == 0) {
988 // We found our device
989 // Strip off the trailing : from the device
990 device[strlen(device)-1] = '\0';
991 if (sscanf(device,"mtd%d", &deviceId) == 1) {
992 sprintf(device, "/dev/block/mtdblock%d", deviceId);
993 Primary_Block_Device = device;
Dees_Troy76543db2013-06-19 16:24:30 +0000994 fclose(fp);
995 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400996 }
997 }
998 }
999 fclose(fp);
1000
1001 return false;
1002}
1003
Dees_Troy51127312012-09-08 13:08:49 -04001004bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
1005 struct statfs st;
1006 string Local_Path = Mount_Point + "/.";
1007
1008 if (!Mount(Display_Error))
1009 return false;
1010
1011 if (statfs(Local_Path.c_str(), &st) != 0) {
1012 if (!Removable) {
1013 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001014 LOGERR("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001015 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001016 LOGINFO("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -04001017 }
1018 return false;
1019 }
1020 Size = (st.f_blocks * st.f_bsize);
1021 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
1022 Free = (st.f_bfree * st.f_bsize);
1023 Backup_Size = Used;
1024 return true;
1025}
1026
1027bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001028 FILE* fp;
1029 char command[255], line[512];
1030 int include_block = 1;
1031 unsigned int min_len;
1032
1033 if (!Mount(Display_Error))
1034 return false;
1035
Dees_Troy38bd7602012-09-14 13:33:53 -04001036 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -04001037 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001038 TWFunc::Exec_Cmd(command);
Dees_Troy51127312012-09-08 13:08:49 -04001039 fp = fopen("/tmp/dfoutput.txt", "rt");
1040 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001041 LOGINFO("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001042 return false;
Dees_Troy51127312012-09-08 13:08:49 -04001043 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001044
1045 while (fgets(line, sizeof(line), fp) != NULL)
1046 {
1047 unsigned long blocks, used, available;
1048 char device[64];
1049 char tmpString[64];
1050
1051 if (strncmp(line, "Filesystem", 10) == 0)
1052 continue;
1053 if (strlen(line) < min_len) {
1054 include_block = 0;
1055 continue;
1056 }
1057 if (include_block) {
1058 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
1059 } else {
1060 // The device block string is so long that the df information is on the next line
1061 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -04001062 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001063 while (tmpString[space_count] == 32)
1064 space_count++;
1065 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
1066 }
1067
1068 // Adjust block size to byte size
1069 Size = blocks * 1024ULL;
1070 Used = used * 1024ULL;
1071 Free = available * 1024ULL;
1072 Backup_Size = Used;
1073 }
1074 fclose(fp);
1075 return true;
1076}
1077
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001078unsigned long long TWPartition::IOCTL_Get_Block_Size() {
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001079 Find_Actual_Block_Device();
Ethan Yonker483e9f42016-01-11 22:21:18 -06001080
1081 return TWFunc::IOCTL_Get_Block_Size(Actual_Block_Device.c_str());
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001082}
1083
Dees_Troy5bf43922012-09-07 16:07:55 -04001084bool TWPartition::Find_Partition_Size(void) {
1085 FILE* fp;
1086 char line[512];
1087 string tmpdevice;
1088
igoriok87e3d932013-01-31 21:03:53 +02001089 fp = fopen("/proc/dumchar_info", "rt");
1090 if (fp != NULL) {
1091 while (fgets(line, sizeof(line), fp) != NULL)
1092 {
1093 char label[32], device[32];
1094 unsigned long size = 0;
1095
thatd43bf2d2014-09-21 23:13:02 +02001096 sscanf(line, "%s %lx %*x %*u %s", label, &size, device);
igoriok87e3d932013-01-31 21:03:53 +02001097
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001098 // Skip header, annotation and blank lines
igoriok87e3d932013-01-31 21:03:53 +02001099 if ((strncmp(device, "/dev/", 5) != 0) || (strlen(line) < 8))
1100 continue;
1101
1102 tmpdevice = "/dev/";
1103 tmpdevice += label;
1104 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
1105 Size = size;
1106 fclose(fp);
1107 return true;
1108 }
1109 }
1110 }
1111
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001112 unsigned long long ioctl_size = IOCTL_Get_Block_Size();
1113 if (ioctl_size) {
1114 Size = ioctl_size;
1115 return true;
1116 }
1117
Dees_Troy5bf43922012-09-07 16:07:55 -04001118 // In this case, we'll first get the partitions we care about (with labels)
1119 fp = fopen("/proc/partitions", "rt");
1120 if (fp == NULL)
1121 return false;
1122
1123 while (fgets(line, sizeof(line), fp) != NULL)
1124 {
1125 unsigned long major, minor, blocks;
1126 char device[512];
Dees_Troy5bf43922012-09-07 16:07:55 -04001127
Dees_Troy63c8df72012-09-10 14:02:05 -04001128 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -04001129 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
1130
1131 tmpdevice = "/dev/block/";
1132 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -04001133 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001134 // Adjust block size to byte size
1135 Size = blocks * 1024ULL;
1136 fclose(fp);
1137 return true;
1138 }
1139 }
1140 fclose(fp);
1141 return false;
1142}
1143
Dees_Troy5bf43922012-09-07 16:07:55 -04001144bool TWPartition::Is_Mounted(void) {
1145 if (!Can_Be_Mounted)
1146 return false;
1147
1148 struct stat st1, st2;
1149 string test_path;
1150
1151 // Check to see if the mount point directory exists
1152 test_path = Mount_Point + "/.";
1153 if (stat(test_path.c_str(), &st1) != 0) return false;
1154
1155 // Check to see if the directory above the mount point exists
1156 test_path = Mount_Point + "/../.";
1157 if (stat(test_path.c_str(), &st2) != 0) return false;
1158
1159 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
1160 int ret = (st1.st_dev != st2.st_dev) ? true : false;
1161
1162 return ret;
1163}
1164
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05001165bool TWPartition::Is_File_System_Writable(void) {
1166 if (!Is_File_System(Current_File_System) || !Is_Mounted())
1167 return false;
1168
1169 string test_path = Mount_Point + "/.";
1170 return (access(test_path.c_str(), W_OK) == 0);
1171}
1172
Dees_Troy5bf43922012-09-07 16:07:55 -04001173bool TWPartition::Mount(bool Display_Error) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001174 int exfat_mounted = 0;
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001175 unsigned long flags = Mount_Flags;
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001176
Dees_Troy5bf43922012-09-07 16:07:55 -04001177 if (Is_Mounted()) {
1178 return true;
1179 } else if (!Can_Be_Mounted) {
1180 return false;
1181 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001182
1183 Find_Actual_Block_Device();
1184
1185 // Check the current file system before mounting
1186 Check_FS_Type();
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001187 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/exfat-fuse")) {
Dees_Troye34c1332013-02-06 19:13:00 +00001188 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 +00001189 LOGINFO("cmd: %s\n", cmd.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001190 string result;
1191 if (TWFunc::Exec_Cmd(cmd, result) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001192 LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001193 Current_File_System = "vfat";
1194 } else {
1195#ifdef TW_NO_EXFAT_FUSE
1196 UnMount(false);
1197 // We'll let the kernel handle it but using exfat-fuse to detect if the file system is actually exfat
1198 // Some kernels let us mount vfat as exfat which doesn't work out too well
1199#else
1200 exfat_mounted = 1;
1201#endif
1202 }
1203 }
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001204
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001205 if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfs-3g") || TWFunc::Path_Exists("/sbin/mount.ntfs"))) {
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001206 string cmd;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001207 string Ntfsmount_Binary = "";
1208
1209 if (TWFunc::Path_Exists("/sbin/ntfs-3g"))
1210 Ntfsmount_Binary = "ntfs-3g";
1211 else if (TWFunc::Path_Exists("/sbin/mount.ntfs"))
1212 Ntfsmount_Binary = "mount.ntfs";
1213
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001214 if (Mount_Read_Only)
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001215 cmd = "/sbin/" + Ntfsmount_Binary + " -o ro " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001216 else
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001217 cmd = "/sbin/" + Ntfsmount_Binary + " " + Actual_Block_Device + " " + Mount_Point;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001218 LOGINFO("cmd: '%s'\n", cmd.c_str());
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001219
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001220 if (TWFunc::Exec_Cmd(cmd) == 0) {
1221 return true;
1222 } else {
1223 LOGINFO("ntfs-3g failed to mount, trying regular mount method.\n");
1224 }
1225 }
1226
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001227 if (Mount_Read_Only)
1228 flags |= MS_RDONLY;
1229
Dees_Troy22042032012-12-18 21:23:08 +00001230 if (Fstab_File_System == "yaffs2") {
1231 // mount an MTD partition as a YAFFS2 filesystem.
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001232 flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
1233 if (Mount_Read_Only)
1234 flags |= MS_RDONLY;
Dees_Troy76543db2013-06-19 16:24:30 +00001235 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
1236 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
1237 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001238 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001239 else
1240 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1241 return false;
1242 } else {
1243 LOGINFO("Mounted '%s' (MTD) as RO\n", Mount_Point.c_str());
1244 return true;
1245 }
1246 } else {
1247 struct stat st;
1248 string test_path = Mount_Point;
1249 if (stat(test_path.c_str(), &st) < 0) {
1250 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001251 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy76543db2013-06-19 16:24:30 +00001252 else
1253 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
1254 return false;
1255 }
1256 mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
1257 if (new_mode != st.st_mode) {
1258 LOGINFO("Fixing execute permissions for %s\n", Mount_Point.c_str());
1259 if (chmod(Mount_Point.c_str(), new_mode) < 0) {
1260 if (Display_Error)
1261 LOGERR("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1262 else
1263 LOGINFO("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
1264 return false;
1265 }
1266 }
Dees_Troy22042032012-12-18 21:23:08 +00001267 return true;
Dees_Troy76543db2013-06-19 16:24:30 +00001268 }
thatc7572eb2015-03-31 18:55:30 +02001269 }
1270
1271 string mount_fs = Current_File_System;
1272 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sys/module/texfat"))
1273 mount_fs = "texfat";
1274
1275 if (!exfat_mounted &&
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001276 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, Mount_Options.c_str()) != 0 &&
1277 mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), mount_fs.c_str(), flags, NULL) != 0) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001278#ifdef TW_NO_EXFAT_FUSE
1279 if (Current_File_System == "exfat") {
Dees_Troy2673cec2013-04-02 20:22:16 +00001280 LOGINFO("Mounting exfat failed, trying vfat...\n");
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001281 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), "vfat", 0, NULL) != 0) {
Dees_Troy85f44ed2013-01-09 18:42:36 +00001282 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001283 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy85f44ed2013-01-09 18:42:36 +00001284 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001285 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05001286 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 +00001287 return false;
Dees_Troy85f44ed2013-01-09 18:42:36 +00001288 }
Dees_Troyb05ddee2013-01-28 20:24:50 +00001289 } else {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001290#endif
bigbiff bigbiff26774a02014-03-29 18:22:00 -04001291 if (!Removable && Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001292 gui_msg(Msg(msg::kError, "fail_mount=Failed to mount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001293 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001294 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
1295 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 +00001296 return false;
1297#ifdef TW_NO_EXFAT_FUSE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001298 }
1299#endif
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001300 }
Ethan Yonker253368a2014-11-25 15:00:52 -06001301
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001302 if (Removable)
1303 Update_Size(Display_Error);
1304
xiaolu9416f4f2015-06-04 08:22:23 +08001305 if (!Symlink_Mount_Point.empty() && TWFunc::Path_Exists(Symlink_Path)) {
codelover2a3d4ce2015-03-14 20:26:49 +08001306 string Command = "mount -o bind '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
Vojtech Bocek05534202013-09-11 08:11:56 +02001307 TWFunc::Exec_Cmd(Command);
Dees_Troy5bf43922012-09-07 16:07:55 -04001308 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001309 return true;
1310}
1311
1312bool TWPartition::UnMount(bool Display_Error) {
1313 if (Is_Mounted()) {
1314 int never_unmount_system;
1315
1316 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
1317 if (never_unmount_system == 1 && Mount_Point == "/system")
1318 return true; // Never unmount system if you're not supposed to unmount it
1319
Matt Mowera8e6d832017-02-14 20:20:59 -06001320 if (Is_Storage && MTP_Storage_ID > 0)
Ethan Yonker726a0202014-12-16 20:01:38 -06001321 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001322
Dees_Troy38bd7602012-09-14 13:33:53 -04001323 if (!Symlink_Mount_Point.empty())
1324 umount(Symlink_Mount_Point.c_str());
1325
Dees_Troyb05ddee2013-01-28 20:24:50 +00001326 umount(Mount_Point.c_str());
1327 if (Is_Mounted()) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001328 if (Display_Error)
Ethan Yonker74db1572015-10-28 12:44:49 -05001329 gui_msg(Msg(msg::kError, "fail_unmount=Failed to unmount '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy5bf43922012-09-07 16:07:55 -04001330 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001331 LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001332 return false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001333 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -04001334 return true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001335 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001336 } else {
1337 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001338 }
1339}
1340
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05001341bool TWPartition::ReMount(bool Display_Error) {
1342 if (UnMount(Display_Error))
1343 return Mount(Display_Error);
1344 return false;
1345}
1346
1347bool TWPartition::ReMount_RW(bool Display_Error) {
1348 // No need to remount if already mounted rw
1349 if (Is_File_System_Writable())
1350 return true;
1351
1352 bool ro = Mount_Read_Only;
1353 int flags = Mount_Flags;
1354
1355 Mount_Read_Only = false;
1356 Mount_Flags &= ~MS_RDONLY;
1357
1358 bool ret = ReMount(Display_Error);
1359
1360 Mount_Read_Only = ro;
1361 Mount_Flags = flags;
1362
1363 return ret;
1364}
1365
Gary Peck43acadf2012-11-21 21:19:01 -08001366bool TWPartition::Wipe(string New_File_System) {
Ethan Yonker726a0202014-12-16 20:01:38 -06001367 bool wiped = false, update_crypt = false, recreate_media = true;
Dees_Troy16c2b312013-01-15 16:51:18 +00001368 int check;
1369 string Layout_Filename = Mount_Point + "/.layout_version";
1370
Dees_Troy38bd7602012-09-14 13:33:53 -04001371 if (!Can_Be_Wiped) {
Matt Mower3c366972015-12-25 19:28:31 -06001372 gui_msg(Msg(msg::kError, "cannot_wipe=Partition {1} cannot be wiped.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001373 return false;
1374 }
1375
Dees_Troyc51f1f92012-09-20 15:32:13 -04001376 if (Mount_Point == "/cache")
Dees_Troy2673cec2013-04-02 20:22:16 +00001377 Log_Offset = 0;
Dees_Troyc51f1f92012-09-20 15:32:13 -04001378
Dees_Troy16c2b312013-01-15 16:51:18 +00001379 if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
1380 TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
1381 else
1382 unlink("/.layout_version");
Dees_Troy38bd7602012-09-14 13:33:53 -04001383
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001384 if (Has_Data_Media && Current_File_System == New_File_System) {
Dees_Troy16c2b312013-01-15 16:51:18 +00001385 wiped = Wipe_Data_Without_Wiping_Media();
Ethan Yonker5eac2222014-06-11 12:22:55 -05001386 recreate_media = false;
Dees_Troy16c2b312013-01-15 16:51:18 +00001387 } else {
Dees_Troy16c2b312013-01-15 16:51:18 +00001388 DataManager::GetValue(TW_RM_RF_VAR, check);
1389
Hashcodedabfd492013-08-29 22:45:30 -07001390 if (check || Use_Rm_Rf)
Dees_Troy16c2b312013-01-15 16:51:18 +00001391 wiped = Wipe_RMRF();
1392 else if (New_File_System == "ext4")
1393 wiped = Wipe_EXT4();
1394 else if (New_File_System == "ext2" || New_File_System == "ext3")
1395 wiped = Wipe_EXT23(New_File_System);
1396 else if (New_File_System == "vfat")
1397 wiped = Wipe_FAT();
1398 else if (New_File_System == "exfat")
1399 wiped = Wipe_EXFAT();
1400 else if (New_File_System == "yaffs2")
1401 wiped = Wipe_MTD();
Dees_Troye5017042013-08-29 16:38:55 +00001402 else if (New_File_System == "f2fs")
1403 wiped = Wipe_F2FS();
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001404 else if (New_File_System == "ntfs")
1405 wiped = Wipe_NTFS();
Dees_Troy16c2b312013-01-15 16:51:18 +00001406 else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001407 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 +00001408 unlink("/.layout_version");
1409 return false;
1410 }
1411 update_crypt = wiped;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001412 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001413
Gary Pecke8bc5d72012-12-21 06:45:25 -08001414 if (wiped) {
Dees_Troy1c1ac442013-01-17 21:42:14 +00001415 if (Mount_Point == "/cache")
1416 DataManager::Output_Version();
1417
Dees_Troy16c2b312013-01-15 16:51:18 +00001418 if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
1419 TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
1420
1421 if (update_crypt) {
1422 Setup_File_System(false);
1423 if (Is_Encrypted && !Is_Decrypted) {
1424 // just wiped an encrypted partition back to its unencrypted state
1425 Is_Encrypted = false;
1426 Is_Decrypted = false;
1427 Decrypted_Block_Device = "";
1428 if (Mount_Point == "/data") {
1429 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1430 DataManager::SetValue(TW_IS_DECRYPTED, 0);
1431 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001432 }
1433 }
Ethan Yonker5eac2222014-06-11 12:22:55 -05001434
Ethan Yonker66a19492015-12-10 10:19:45 -06001435 if (Has_Data_Media && recreate_media) {
Ethan Yonker5eac2222014-06-11 12:22:55 -05001436 Recreate_Media_Folder();
1437 }
Matt Mower209c9632016-01-20 12:08:35 -06001438 if (Is_Storage && Mount(false))
1439 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Gary Pecke8bc5d72012-12-21 06:45:25 -08001440 }
Matt Mower209c9632016-01-20 12:08:35 -06001441
Gary Pecke8bc5d72012-12-21 06:45:25 -08001442 return wiped;
Dees_Troy51a0e822012-09-05 15:24:24 -04001443}
1444
Gary Peck43acadf2012-11-21 21:19:01 -08001445bool TWPartition::Wipe() {
Gary Peck82599a82012-11-21 16:23:12 -08001446 if (Is_File_System(Current_File_System))
1447 return Wipe(Current_File_System);
1448 else
1449 return Wipe(Fstab_File_System);
Gary Peck43acadf2012-11-21 21:19:01 -08001450}
1451
Dees_Troye58d5262012-09-21 12:27:57 -04001452bool TWPartition::Wipe_AndSec(void) {
1453 if (!Has_Android_Secure)
1454 return false;
1455
Dees_Troye58d5262012-09-21 12:27:57 -04001456 if (!Mount(true))
1457 return false;
1458
Ethan Yonker74db1572015-10-28 12:44:49 -05001459 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001460 TWFunc::removeDir(Mount_Point + "/.android_secure/", true);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001461 return true;
Dees_Troye58d5262012-09-21 12:27:57 -04001462}
1463
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001464bool TWPartition::Can_Repair() {
Ethan Yonkera2719152015-05-28 09:44:41 -05001465 if (Mount_Read_Only)
1466 return false;
Matt Mower18794c82015-11-11 16:22:45 -06001467 if (Current_File_System == "vfat" && TWFunc::Path_Exists("/sbin/fsck.fat"))
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001468 return true;
1469 else if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/e2fsck"))
1470 return true;
1471 else if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/fsck.exfat"))
1472 return true;
1473 else if (Current_File_System == "f2fs" && TWFunc::Path_Exists("/sbin/fsck.f2fs"))
1474 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001475 else if (Current_File_System == "ntfs" && (TWFunc::Path_Exists("/sbin/ntfsfix") || TWFunc::Path_Exists("/sbin/fsck.ntfs")))
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001476 return true;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001477 return false;
1478}
1479
1480bool TWPartition::Repair() {
1481 string command;
1482
1483 if (Current_File_System == "vfat") {
Matt Mower18794c82015-11-11 16:22:45 -06001484 if (!TWFunc::Path_Exists("/sbin/fsck.fat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001485 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001486 return false;
1487 }
1488 if (!UnMount(true))
1489 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001490 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.fat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001491 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06001492 command = "/sbin/fsck.fat -y " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001493 LOGINFO("Repair command: %s\n", command.c_str());
1494 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001495 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001496 return true;
1497 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001498 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001499 return false;
1500 }
1501 }
1502 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1503 if (!TWFunc::Path_Exists("/sbin/e2fsck")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001504 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001505 return false;
1506 }
1507 if (!UnMount(true))
1508 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001509 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("e2fsck"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001510 Find_Actual_Block_Device();
Ethan Yonkera2719152015-05-28 09:44:41 -05001511 command = "/sbin/e2fsck -fp " + Actual_Block_Device;
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001512 LOGINFO("Repair command: %s\n", command.c_str());
1513 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001514 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001515 return true;
1516 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001517 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001518 return false;
1519 }
1520 }
1521 if (Current_File_System == "exfat") {
1522 if (!TWFunc::Path_Exists("/sbin/fsck.exfat")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001523 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001524 return false;
1525 }
1526 if (!UnMount(true))
1527 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001528 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.exfat"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001529 Find_Actual_Block_Device();
1530 command = "/sbin/fsck.exfat " + Actual_Block_Device;
1531 LOGINFO("Repair command: %s\n", command.c_str());
1532 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001533 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001534 return true;
1535 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001536 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001537 return false;
1538 }
1539 }
1540 if (Current_File_System == "f2fs") {
1541 if (!TWFunc::Path_Exists("/sbin/fsck.f2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001542 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001543 return false;
1544 }
1545 if (!UnMount(true))
1546 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001547 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)("fsck.f2fs"));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001548 Find_Actual_Block_Device();
1549 command = "/sbin/fsck.f2fs " + Actual_Block_Device;
1550 LOGINFO("Repair command: %s\n", command.c_str());
1551 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001552 gui_msg("done=Done.");
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001553 return true;
1554 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001555 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001556 return false;
1557 }
1558 }
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001559 if (Current_File_System == "ntfs") {
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001560 string Ntfsfix_Binary;
1561 if (TWFunc::Path_Exists("/sbin/ntfsfix"))
1562 Ntfsfix_Binary = "ntfsfix";
1563 else if (TWFunc::Path_Exists("/sbin/fsck.ntfs"))
1564 Ntfsfix_Binary = "fsck.ntfs";
1565 else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001566 gui_msg(Msg(msg::kError, "repair_not_exist={1} does not exist! Cannot repair!")("ntfsfix"));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001567 return false;
1568 }
1569 if (!UnMount(true))
1570 return false;
Greg Wallace2d653402015-12-29 14:19:21 -05001571 gui_msg(Msg("repairing_using=Repairing {1} using {2}...")(Display_Name)(Ntfsfix_Binary));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001572 Find_Actual_Block_Device();
Greg Wallaceb39e6c62015-12-29 00:55:26 -05001573 command = "/sbin/" + Ntfsfix_Binary + " " + Actual_Block_Device;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001574 LOGINFO("Repair command: %s\n", command.c_str());
1575 if (TWFunc::Exec_Cmd(command) == 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001576 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001577 return true;
1578 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001579 gui_msg(Msg(msg::kError, "unable_repair=Unable to repair {1}.")(Display_Name));
Ethan Yonkerb81d9052015-07-09 13:20:53 -05001580 return false;
1581 }
1582 }
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001583 return false;
1584}
1585
Ethan Yonkera2719152015-05-28 09:44:41 -05001586bool TWPartition::Can_Resize() {
1587 if (Mount_Read_Only)
1588 return false;
1589 if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/resize2fs"))
1590 return true;
1591 return false;
1592}
1593
1594bool TWPartition::Resize() {
1595 string command;
1596
1597 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1598 if (!Can_Repair()) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001599 LOGINFO("Cannot resize %s because %s cannot be repaired before resizing.\n", Display_Name.c_str(), Display_Name.c_str());
1600 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001601 return false;
1602 }
1603 if (!TWFunc::Path_Exists("/sbin/resize2fs")) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001604 LOGINFO("resize2fs does not exist! Cannot resize!\n");
1605 gui_msg(Msg(msg::kError, "cannot_resize=Cannot resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001606 return false;
1607 }
1608 // Repair will unmount so no need to do it twice
Ethan Yonker74db1572015-10-28 12:44:49 -05001609 gui_msg(Msg("repair_resize=Repairing {1} before resizing.")( Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001610 if (!Repair())
1611 return false;
Ethan Yonker74db1572015-10-28 12:44:49 -05001612 gui_msg(Msg("resizing=Resizing {1} using {2}...")(Display_Name)("resize2fs"));
Ethan Yonkera2719152015-05-28 09:44:41 -05001613 Find_Actual_Block_Device();
1614 command = "/sbin/resize2fs " + Actual_Block_Device;
1615 if (Length != 0) {
Ethan Yonkerd18a8212015-12-14 10:17:00 -06001616 unsigned long long Actual_Size = IOCTL_Get_Block_Size();
1617 if (Actual_Size == 0)
1618 return false;
Ethan Yonkera2719152015-05-28 09:44:41 -05001619
Ethan Yonkera2719152015-05-28 09:44:41 -05001620 unsigned long long Block_Count;
1621 if (Length < 0) {
1622 // Reduce overall size by this length
1623 Block_Count = (Actual_Size / 1024LLU) - ((unsigned long long)(Length * -1) / 1024LLU);
1624 } else {
1625 // This is the size, not a size reduction
1626 Block_Count = ((unsigned long long)(Length) / 1024LLU);
1627 }
1628 char temp[256];
1629 sprintf(temp, "%llu", Block_Count);
1630 command += " ";
1631 command += temp;
1632 command += "K";
1633 }
1634 LOGINFO("Resize command: %s\n", command.c_str());
1635 if (TWFunc::Exec_Cmd(command) == 0) {
1636 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001637 gui_msg("done=Done.");
Ethan Yonkera2719152015-05-28 09:44:41 -05001638 return true;
1639 } else {
1640 Update_Size(true);
Ethan Yonker74db1572015-10-28 12:44:49 -05001641 gui_msg(Msg(msg::kError, "unable_resize=Unable to resize {1}.")(Display_Name));
Ethan Yonkera2719152015-05-28 09:44:41 -05001642 return false;
1643 }
1644 }
1645 return false;
1646}
1647
bigbiffce8f83c2015-12-12 18:30:21 -05001648bool TWPartition::Backup(PartitionSettings *part_settings, pid_t *tar_fork_pid) {
1649 if (Backup_Method == BM_FILES)
1650 return Backup_Tar(part_settings, tar_fork_pid);
1651 else if (Backup_Method == BM_DD)
1652 return Backup_Image(part_settings);
1653 else if (Backup_Method == BM_FLASH_UTILS)
1654 return Backup_Dump_Image(part_settings);
Dees_Troy2673cec2013-04-02 20:22:16 +00001655 LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001656 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001657}
1658
bigbiffce8f83c2015-12-12 18:30:21 -05001659bool TWPartition::Restore(PartitionSettings *part_settings) {
Matt Mower3c366972015-12-25 19:28:31 -06001660 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonkere080c1f2016-09-19 13:50:25 -05001661 LOGINFO("Restore filename is: %s/%s\n", part_settings->Backup_Folder.c_str(), Backup_FileName.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001662
bigbiffce8f83c2015-12-12 18:30:21 -05001663 string Restore_File_System = Get_Restore_File_System(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001664
1665 if (Is_File_System(Restore_File_System))
bigbiffce8f83c2015-12-12 18:30:21 -05001666 return Restore_Tar(part_settings);
1667 else if (Is_Image(Restore_File_System))
1668 return Restore_Image(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001669
1670 LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str());
1671 return false;
1672}
1673
bigbiffce8f83c2015-12-12 18:30:21 -05001674string TWPartition::Get_Restore_File_System(PartitionSettings *part_settings) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001675 size_t first_period, second_period;
1676 string Restore_File_System;
1677
Gary Peck43acadf2012-11-21 21:19:01 -08001678 // Parse backup filename to extract the file system before wiping
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05001679 first_period = Backup_FileName.find(".");
Gary Peck43acadf2012-11-21 21:19:01 -08001680 if (first_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001681 LOGERR("Unable to find file system (first period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001682 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001683 }
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05001684 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
Gary Peck43acadf2012-11-21 21:19:01 -08001685 second_period = Restore_File_System.find(".");
1686 if (second_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001687 LOGERR("Unable to find file system (second period).\n");
thatd43bf2d2014-09-21 23:13:02 +02001688 return string();
Gary Peck43acadf2012-11-21 21:19:01 -08001689 }
1690 Restore_File_System.resize(second_period);
Matt Mowera0cd91d2016-12-30 18:21:42 -06001691 LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001692 return Restore_File_System;
Dees_Troy51a0e822012-09-05 15:24:24 -04001693}
1694
1695string TWPartition::Backup_Method_By_Name() {
bigbiffce8f83c2015-12-12 18:30:21 -05001696 if (Backup_Method == BM_NONE)
Dees_Troy38bd7602012-09-14 13:33:53 -04001697 return "none";
bigbiffce8f83c2015-12-12 18:30:21 -05001698 else if (Backup_Method == BM_FILES)
Dees_Troy38bd7602012-09-14 13:33:53 -04001699 return "files";
bigbiffce8f83c2015-12-12 18:30:21 -05001700 else if (Backup_Method == BM_DD)
Dees_Troy38bd7602012-09-14 13:33:53 -04001701 return "dd";
bigbiffce8f83c2015-12-12 18:30:21 -05001702 else if (Backup_Method == BM_FLASH_UTILS)
Dees_Troy38bd7602012-09-14 13:33:53 -04001703 return "flash_utils";
1704 else
1705 return "undefined";
1706 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -04001707}
1708
1709bool TWPartition::Decrypt(string Password) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001710 LOGINFO("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001711 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -04001712 return 1;
1713}
1714
1715bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001716 bool Save_Data_Media = Has_Data_Media;
1717
1718 if (!UnMount(true))
1719 return false;
1720
Dees_Troy38bd7602012-09-14 13:33:53 -04001721 Has_Data_Media = false;
Dees_Troy74fb2e92013-04-15 14:35:47 +00001722 Decrypted_Block_Device = "";
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001723#ifdef TW_INCLUDE_CRYPTO
Ethan Yonker1b190162016-12-05 15:25:19 -06001724 if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001725 if (!UnMount(true))
1726 return false;
Matt Mower2b18a532015-02-20 16:58:05 -06001727 if (delete_crypto_blk_dev((char*)("userdata")) != 0) {
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001728 LOGERR("Error deleting crypto block device, continuing anyway.\n");
1729 }
1730 }
1731#endif
Dees_Troy74fb2e92013-04-15 14:35:47 +00001732 Is_Decrypted = false;
1733 Is_Encrypted = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001734 Find_Actual_Block_Device();
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001735 if (Crypto_Key_Location == "footer") {
1736 int newlen, fd;
1737 if (Length != 0) {
1738 newlen = Length;
1739 if (newlen < 0)
1740 newlen = newlen * -1;
1741 } else {
1742 newlen = CRYPT_FOOTER_OFFSET;
1743 }
1744 if ((fd = open(Actual_Block_Device.c_str(), O_RDWR)) < 0) {
1745 gui_print_color("warning", "Unable to open '%s' to wipe crypto key\n", Actual_Block_Device.c_str());
1746 } else {
1747 unsigned int block_count;
1748 if ((ioctl(fd, BLKGETSIZE, &block_count)) == -1) {
1749 gui_print_color("warning", "Unable to get block size for wiping crypto footer.\n");
1750 } else {
1751 off64_t offset = ((off64_t)block_count * 512) - newlen;
1752 if (lseek64(fd, offset, SEEK_SET) == -1) {
1753 gui_print_color("warning", "Unable to lseek64 for wiping crypto footer.\n");
1754 } else {
1755 void* buffer = malloc(newlen);
1756 if (!buffer) {
1757 gui_print_color("warning", "Failed to malloc for wiping crypto footer.\n");
1758 } else {
1759 memset(buffer, 0, newlen);
1760 int ret = write(fd, buffer, newlen);
1761 if (ret != newlen) {
1762 gui_print_color("warning", "Failed to wipe crypto footer.\n");
1763 } else {
1764 LOGINFO("Successfully wiped crypto footer.\n");
1765 }
Matt Mower13a8f0b2015-09-26 15:40:03 -05001766 free(buffer);
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001767 }
1768 }
1769 }
1770 close(fd);
1771 }
1772 } else {
Ethan Yonkerc2dafbb2016-03-15 22:20:59 -05001773 if (TWFunc::IOCTL_Get_Block_Size(Crypto_Key_Location.c_str()) >= 16384LLU) {
1774 string Command = "dd of='" + Crypto_Key_Location + "' if=/dev/zero bs=16384 count=1";
1775 TWFunc::Exec_Cmd(Command);
1776 } else {
1777 LOGINFO("Crypto key location reports size < 16K so not wiping crypto footer.\n");
1778 }
Ethan Yonkerbc85b632015-08-09 12:48:14 -05001779 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001780 if (Wipe(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001781 Has_Data_Media = Save_Data_Media;
1782 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
1783 Recreate_Media_Folder();
Ethan Yonker726a0202014-12-16 20:01:38 -06001784 if (Mount(false))
1785 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001786 }
Ethan Yonkerd79d9bc2014-12-20 15:38:29 -06001787 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
Ethan Yonker83e82572014-04-04 10:59:28 -05001788#ifndef TW_OEM_BUILD
Ethan Yonker74db1572015-10-28 12:44:49 -05001789 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 -05001790#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001791 return true;
1792 } else {
1793 Has_Data_Media = Save_Data_Media;
Ethan Yonker74db1572015-10-28 12:44:49 -05001794 gui_err("format_data_err=Unable to format to remove encryption.");
Ethan Yonker726a0202014-12-16 20:01:38 -06001795 if (Has_Data_Media && Mount(false))
1796 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04001797 return false;
1798 }
1799 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001800}
1801
1802void TWPartition::Check_FS_Type() {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001803 const char* type;
1804 blkid_probe pr;
Dees_Troy5bf43922012-09-07 16:07:55 -04001805
Dees_Troy68cab492012-12-12 19:29:35 +00001806 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd" || Fstab_File_System == "bml" || Ignore_Blkid)
1807 return; // Running blkid on some mtd devices causes a massive crash or needs to be skipped
Dees_Troy5bf43922012-09-07 16:07:55 -04001808
Dees_Troy38bd7602012-09-14 13:33:53 -04001809 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -04001810 if (!Is_Present)
1811 return;
Dees_Troy51127312012-09-08 13:08:49 -04001812
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001813 pr = blkid_new_probe_from_filename(Actual_Block_Device.c_str());
1814 if (blkid_do_fullprobe(pr)) {
1815 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001816 LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001817 return;
Dees_Troy5bf43922012-09-07 16:07:55 -04001818 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001819
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001820 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001821 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001822 LOGINFO("can't find filesystem on device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001823 return;
1824 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001825
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001826 Current_File_System = type;
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001827 blkid_free_probe(pr);
Dees_Troy51a0e822012-09-05 15:24:24 -04001828}
1829
Gary Peck43acadf2012-11-21 21:19:01 -08001830bool TWPartition::Wipe_EXT23(string File_System) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001831 if (!UnMount(true))
1832 return false;
1833
Dees_Troy43d8b002012-09-17 16:00:01 -04001834 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001835 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001836
Greg Wallace4b44fef2015-12-29 15:33:24 -05001837 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mke2fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001838 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001839 command = "mke2fs -t " + File_System + " -m 0 " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001840 LOGINFO("mke2fs command: %s\n", command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001841 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001842 Current_File_System = File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04001843 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001844 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001845 return true;
1846 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001847 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001848 return false;
1849 }
1850 } else
1851 return Wipe_RMRF();
1852
1853 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001854}
1855
1856bool TWPartition::Wipe_EXT4() {
Ethan Yonker25f20c12014-10-14 09:04:43 -05001857 Find_Actual_Block_Device();
1858 if (!Is_Present) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001859 LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
1860 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Ethan Yonker25f20c12014-10-14 09:04:43 -05001861 return false;
1862 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001863 if (!UnMount(true))
1864 return false;
1865
Matt Mower87413642017-01-17 21:14:46 -06001866#if defined(USE_EXT4)
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001867 int ret;
1868 char *secontext = NULL;
1869
Greg Wallace4b44fef2015-12-29 15:33:24 -05001870 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001871
Dees Troy99c8dbf2014-03-10 16:53:58 +00001872 if (!selinux_handle || selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001873 LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
1874 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
1875 } else {
1876 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
1877 }
1878 if (ret != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001879 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troya95f55c2013-08-17 13:14:43 +00001880 return false;
1881 } else {
bigbiff bigbiffc49d7062013-10-11 20:28:00 -04001882 string sedir = Mount_Point + "/lost+found";
1883 PartitionManager.Mount_By_Path(sedir.c_str(), true);
1884 rmdir(sedir.c_str());
1885 mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
Dees_Troya95f55c2013-08-17 13:14:43 +00001886 return true;
1887 }
1888#else
Dees_Troy43d8b002012-09-17 16:00:01 -04001889 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001890 string Command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001891
Greg Wallace4b44fef2015-12-29 15:33:24 -05001892 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("make_ext4fs"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001893 Find_Actual_Block_Device();
1894 Command = "make_ext4fs";
1895 if (!Is_Decrypted && Length != 0) {
1896 // Only use length if we're not decrypted
1897 char len[32];
1898 sprintf(len, "%i", Length);
1899 Command += " -l ";
1900 Command += len;
1901 }
Dees_Troy5295d582013-09-06 15:51:08 +00001902 if (TWFunc::Path_Exists("/file_contexts")) {
1903 Command += " -S /file_contexts";
1904 }
1905 Command += " -a " + Mount_Point + " " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001906 LOGINFO("make_ext4fs command: %s\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001907 if (TWFunc::Exec_Cmd(Command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001908 Current_File_System = "ext4";
Dees_Troye58d5262012-09-21 12:27:57 -04001909 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001910 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001911 return true;
1912 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001913 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001914 return false;
1915 }
1916 } else
Gary Peck43acadf2012-11-21 21:19:01 -08001917 return Wipe_EXT23("ext4");
Dees_Troya95f55c2013-08-17 13:14:43 +00001918#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001919 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001920}
1921
1922bool TWPartition::Wipe_FAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001923 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001924
Matt Mower18794c82015-11-11 16:22:45 -06001925 if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001926 if (!UnMount(true))
1927 return false;
1928
Greg Wallace4b44fef2015-12-29 15:33:24 -05001929 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001930 Find_Actual_Block_Device();
Matt Mower18794c82015-11-11 16:22:45 -06001931 command = "mkfs.fat " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001932 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001933 Current_File_System = "vfat";
Dees_Troye58d5262012-09-21 12:27:57 -04001934 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001935 gui_msg("done=Done.");
Dees_Troy38bd7602012-09-14 13:33:53 -04001936 return true;
1937 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001938 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troy38bd7602012-09-14 13:33:53 -04001939 return false;
1940 }
1941 return true;
1942 }
1943 else
1944 return Wipe_RMRF();
1945
1946 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001947}
1948
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001949bool TWPartition::Wipe_EXFAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001950 string command;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001951
1952 if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
1953 if (!UnMount(true))
1954 return false;
1955
Greg Wallace4b44fef2015-12-29 15:33:24 -05001956 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkexfatfs"));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001957 Find_Actual_Block_Device();
1958 command = "mkexfatfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001959 if (TWFunc::Exec_Cmd(command) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001960 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05001961 gui_msg("done=Done.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001962 return true;
1963 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05001964 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001965 return false;
1966 }
1967 return true;
1968 }
1969 return false;
1970}
1971
Dees_Troy38bd7602012-09-14 13:33:53 -04001972bool TWPartition::Wipe_MTD() {
1973 if (!UnMount(true))
1974 return false;
1975
Greg Wallace4b44fef2015-12-29 15:33:24 -05001976 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("MTD"));
Dees_Troy38bd7602012-09-14 13:33:53 -04001977
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001978 mtd_scan_partitions();
1979 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
1980 if (mtd == NULL) {
1981 LOGERR("No mtd partition named '%s'", MTD_Name.c_str());
1982 return false;
1983 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001984
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001985 MtdWriteContext* ctx = mtd_write_partition(mtd);
1986 if (ctx == NULL) {
1987 LOGERR("Can't write '%s', failed to format.", MTD_Name.c_str());
1988 return false;
1989 }
1990 if (mtd_erase_blocks(ctx, -1) == -1) {
1991 mtd_write_close(ctx);
1992 LOGERR("Failed to format '%s'", MTD_Name.c_str());
1993 return false;
1994 }
1995 if (mtd_write_close(ctx) != 0) {
1996 LOGERR("Failed to close '%s'", MTD_Name.c_str());
1997 return false;
1998 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001999 Current_File_System = "yaffs2";
Dees_Troye58d5262012-09-21 12:27:57 -04002000 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002001 gui_msg("done=Done.");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02002002 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002003}
2004
2005bool TWPartition::Wipe_RMRF() {
Dees_Troy38bd7602012-09-14 13:33:53 -04002006 if (!Mount(true))
2007 return false;
Ethan Yonker726a0202014-12-16 20:01:38 -06002008 // This is the only wipe that leaves the partition mounted, so we
2009 // must manually remove the partition from MTP if it is a storage
2010 // partition.
2011 if (Is_Storage)
2012 PartitionManager.Remove_MTP_Storage(MTP_Storage_ID);
Dees_Troy38bd7602012-09-14 13:33:53 -04002013
Ethan Yonker74db1572015-10-28 12:44:49 -05002014 gui_msg(Msg("remove_all=Removing all files under '{1}'")(Mount_Point));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002015 TWFunc::removeDir(Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002016 Recreate_AndSec_Folder();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002017 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002018}
2019
Dees_Troye5017042013-08-29 16:38:55 +00002020bool TWPartition::Wipe_F2FS() {
Vojtech Bocek05534202013-09-11 08:11:56 +02002021 string command;
Dees_Troye5017042013-08-29 16:38:55 +00002022
2023 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
2024 if (!UnMount(true))
2025 return false;
2026
Greg Wallace4b44fef2015-12-29 15:33:24 -05002027 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.f2fs"));
Dees_Troye5017042013-08-29 16:38:55 +00002028 Find_Actual_Block_Device();
Greg Wallace558aef72016-01-19 21:14:30 -05002029 command = "mkfs.f2fs -t 0";
dhacker29a3fa75f2015-01-17 19:42:33 -05002030 if (!Is_Decrypted && Length != 0) {
2031 // Only use length if we're not decrypted
2032 char len[32];
2033 int mod_length = Length;
2034 if (Length < 0)
2035 mod_length *= -1;
2036 sprintf(len, "%i", mod_length);
2037 command += " -r ";
2038 command += len;
2039 }
2040 command += " " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02002041 if (TWFunc::Exec_Cmd(command) == 0) {
Dees_Troye5017042013-08-29 16:38:55 +00002042 Recreate_AndSec_Folder();
Ethan Yonker74db1572015-10-28 12:44:49 -05002043 gui_msg("done=Done.");
Dees_Troye5017042013-08-29 16:38:55 +00002044 return true;
2045 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002046 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
Dees_Troye5017042013-08-29 16:38:55 +00002047 return false;
2048 }
2049 return true;
2050 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002051 LOGINFO("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
Dees_Troye5017042013-08-29 16:38:55 +00002052 return Wipe_RMRF();
2053 }
2054 return false;
2055}
2056
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002057bool TWPartition::Wipe_NTFS() {
2058 string command;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002059 string Ntfsmake_Binary;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002060
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002061 if (TWFunc::Path_Exists("/sbin/mkntfs"))
2062 Ntfsmake_Binary = "mkntfs";
2063 else if (TWFunc::Path_Exists("/sbin/mkfs.ntfs"))
2064 Ntfsmake_Binary = "mkfs.ntfs";
2065 else
2066 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002067
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002068 if (!UnMount(true))
2069 return false;
2070
Greg Wallace4b44fef2015-12-29 15:33:24 -05002071 gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)(Ntfsmake_Binary));
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002072 Find_Actual_Block_Device();
2073 command = "/sbin/" + Ntfsmake_Binary + " " + Actual_Block_Device;
2074 if (TWFunc::Exec_Cmd(command) == 0) {
2075 Recreate_AndSec_Folder();
2076 gui_msg("done=Done.");
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002077 return true;
Greg Wallaceb39e6c62015-12-29 00:55:26 -05002078 } else {
2079 gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
2080 return false;
Ethan Yonkerb81d9052015-07-09 13:20:53 -05002081 }
2082 return false;
2083}
2084
Dees_Troy51a0e822012-09-05 15:24:24 -04002085bool TWPartition::Wipe_Data_Without_Wiping_Media() {
Ethan Yonker83e82572014-04-04 10:59:28 -05002086#ifdef TW_OEM_BUILD
2087 // In an OEM Build we want to do a full format
2088 return Wipe_Encryption();
2089#else
Ethan Yonker66a19492015-12-10 10:19:45 -06002090 bool ret = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04002091
Dees_Troy38bd7602012-09-14 13:33:53 -04002092 if (!Mount(true))
2093 return false;
2094
Ethan Yonker74db1572015-10-28 12:44:49 -05002095 gui_msg("wiping_data=Wiping data without wiping /data/media ...");
Ethan Yonker66a19492015-12-10 10:19:45 -06002096 ret = Wipe_Data_Without_Wiping_Media_Func(Mount_Point + "/");
2097 if (ret)
2098 gui_msg("done=Done.");
2099 return ret;
2100#endif // ifdef TW_OEM_BUILD
2101}
2102
2103bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unused) {
2104 string dir;
Dees_Troy38bd7602012-09-14 13:33:53 -04002105
2106 DIR* d;
Ethan Yonker66a19492015-12-10 10:19:45 -06002107 d = opendir(parent.c_str());
Dees_Troy16b74352012-11-14 22:27:31 +00002108 if (d != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002109 struct dirent* de;
2110 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002111 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05002112
Ethan Yonker66a19492015-12-10 10:19:45 -06002113 dir = parent;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002114 dir.append(de->d_name);
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002115 if (wipe_exclusions.check_skip_dirs(dir)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002116 LOGINFO("skipped '%s'\n", dir.c_str());
2117 continue;
2118 }
Dees_Troyce675462013-01-09 19:48:21 +00002119 if (de->d_type == DT_DIR) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002120 dir.append("/");
2121 if (!Wipe_Data_Without_Wiping_Media_Func(dir)) {
2122 closedir(d);
2123 return false;
2124 }
2125 rmdir(dir.c_str());
bigbiff bigbiff98f1f902013-01-19 18:46:13 -05002126 } 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 +03002127 if (unlink(dir.c_str()) != 0)
Ethan Yonker79f88bd2016-12-09 14:52:12 -06002128 LOGINFO("Unable to unlink '%s': %s\n", dir.c_str(), strerror(errno));
Dees_Troyce675462013-01-09 19:48:21 +00002129 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002130 }
2131 closedir(d);
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05002132
Dees_Troy16b74352012-11-14 22:27:31 +00002133 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04002134 }
Ethan Yonker74db1572015-10-28 12:44:49 -05002135 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Mount_Point)(strerror(errno)));
Dees_Troy16b74352012-11-14 22:27:31 +00002136 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04002137}
2138
bigbiffce8f83c2015-12-12 18:30:21 -05002139bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002140 string Full_FileName;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002141 twrpTar tar;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05002142
Dees_Troy43d8b002012-09-17 16:00:01 -04002143 if (!Mount(true))
2144 return false;
2145
Dees_Troya13d74f2013-03-24 08:54:55 -05002146 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up");
Ethan Yonker74db1572015-10-28 12:44:49 -05002147 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002148
Ethan Yonker472f5062016-02-25 13:47:30 -06002149 DataManager::GetValue(TW_USE_COMPRESSION_VAR, tar.use_compression);
Matt Mowerbb81e5d2014-03-20 18:05:41 -05002150
Dees_Troy83bd4832013-05-04 12:39:56 +00002151#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
Ethan Yonker472f5062016-02-25 13:47:30 -06002152 if (Can_Encrypt_Backup) {
2153 DataManager::GetValue("tw_encrypt_backup", tar.use_encryption);
2154 if (tar.use_encryption) {
2155 if (Use_Userdata_Encryption)
2156 tar.userdata_encryption = tar.use_encryption;
2157 string Password;
2158 DataManager::GetValue("tw_backup_password", Password);
2159 tar.setpassword(Password);
2160 } else {
2161 tar.use_encryption = 0;
2162 }
Dees_Troy83bd4832013-05-04 12:39:56 +00002163 }
2164#endif
Dees_Troy43d8b002012-09-17 16:00:01 -04002165
Ethan Yonker472f5062016-02-25 13:47:30 -06002166 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002167 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker01f4e032017-02-03 15:30:52 -06002168 if (Has_Data_Media)
2169 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 -05002170 tar.part_settings = part_settings;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002171 tar.backup_exclusions = &backup_exclusions;
Dees Troye0a433a2013-12-02 04:10:37 +00002172 tar.setdir(Backup_Path);
2173 tar.setfn(Full_FileName);
2174 tar.setsize(Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002175 tar.partition_name = Backup_Name;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002176 tar.backup_folder = part_settings->Backup_Folder;
bigbiffce8f83c2015-12-12 18:30:21 -05002177 if (tar.createTarFork(tar_fork_pid) != 0)
Dees Troye0a433a2013-12-02 04:10:37 +00002178 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04002179 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002180}
2181
bigbiffce8f83c2015-12-12 18:30:21 -05002182bool TWPartition::Backup_Image(PartitionSettings *part_settings) {
2183 string Full_FileName, adb_file_name;
igoriok87e3d932013-01-31 21:03:53 +02002184
Ethan Yonker74db1572015-10-28 12:44:49 -05002185 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2186 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002187
Ethan Yonker472f5062016-02-25 13:47:30 -06002188 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Dees_Troy43d8b002012-09-17 16:00:01 -04002189
bigbiffce8f83c2015-12-12 18:30:21 -05002190 if (part_settings->adbbackup) {
2191 Full_FileName = TW_ADB_BACKUP;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002192 adb_file_name = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002193 }
2194 else
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002195 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002196
2197 part_settings->total_restore_size = Backup_Size;
2198
2199 if (part_settings->adbbackup) {
2200 if (!twadbbu::Write_TWIMG(adb_file_name, Backup_Size))
2201 return false;
2202 }
2203
2204 if (!Raw_Read_Write(part_settings))
Ethan Yonker472f5062016-02-25 13:47:30 -06002205 return false;
2206
bigbiffce8f83c2015-12-12 18:30:21 -05002207 if (part_settings->adbbackup) {
2208 if (!twadbbu::Write_TWEOF())
2209 return false;
Dees_Troy7c2dec82012-09-26 09:49:14 -04002210 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002211 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002212}
2213
bigbiffce8f83c2015-12-12 18:30:21 -05002214bool TWPartition::Raw_Read_Write(PartitionSettings *part_settings) {
2215 unsigned long long RW_Block_Size, Remain = Backup_Size;
2216 int src_fd = -1, dest_fd = -1;
2217 ssize_t bs;
Ethan Yonker472f5062016-02-25 13:47:30 -06002218 bool ret = false;
2219 void* buffer = NULL;
2220 unsigned long long backedup_size = 0;
bigbiffce8f83c2015-12-12 18:30:21 -05002221 string srcfn, destfn;
Ethan Yonker472f5062016-02-25 13:47:30 -06002222
bigbiffce8f83c2015-12-12 18:30:21 -05002223 if (part_settings->PM_Method == PM_BACKUP) {
2224 srcfn = Actual_Block_Device;
2225 if (part_settings->adbbackup)
2226 destfn = TW_ADB_BACKUP;
2227 else
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002228 destfn = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002229 }
2230 else {
2231 destfn = Actual_Block_Device;
2232 if (part_settings->adbbackup) {
2233 srcfn = TW_ADB_RESTORE;
2234 } else {
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002235 srcfn = part_settings->Backup_Folder + "/" + Backup_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002236 Remain = TWFunc::Get_File_Size(srcfn);
2237 }
2238 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002239
bigbiffce8f83c2015-12-12 18:30:21 -05002240 src_fd = open(srcfn.c_str(), O_RDONLY | O_LARGEFILE);
Ethan Yonker472f5062016-02-25 13:47:30 -06002241 if (src_fd < 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05002242 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(srcfn.c_str())(strerror(errno)));
Ethan Yonker472f5062016-02-25 13:47:30 -06002243 return false;
2244 }
bigbiffce8f83c2015-12-12 18:30:21 -05002245
2246 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 -06002247 if (dest_fd < 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05002248 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(destfn.c_str())(strerror(errno)));
Ethan Yonker472f5062016-02-25 13:47:30 -06002249 goto exit;
2250 }
bigbiffce8f83c2015-12-12 18:30:21 -05002251
2252 LOGINFO("Reading '%s', writing '%s'\n", srcfn.c_str(), destfn.c_str());
2253
2254 if (part_settings->adbbackup) {
2255 RW_Block_Size = MAX_ADB_READ;
2256 bs = MAX_ADB_READ;
2257 }
2258 else {
2259 RW_Block_Size = 1048576LLU; // 1MB
2260 bs = (ssize_t)(RW_Block_Size);
2261 }
2262
Ethan Yonker472f5062016-02-25 13:47:30 -06002263 buffer = malloc((size_t)bs);
2264 if (!buffer) {
2265 LOGINFO("Raw_Read_Write failed to malloc\n");
2266 goto exit;
2267 }
bigbiffce8f83c2015-12-12 18:30:21 -05002268
2269 if (part_settings->progress)
2270 part_settings->progress->SetPartitionSize(part_settings->total_restore_size);
2271
Ethan Yonker472f5062016-02-25 13:47:30 -06002272 while (Remain > 0) {
2273 if (Remain < RW_Block_Size)
bigbiffce8f83c2015-12-12 18:30:21 -05002274 bs = (ssize_t)(Remain);
Matt Mowera8a89d12016-12-30 18:10:37 -06002275 if (read(src_fd, buffer, bs) != bs) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002276 LOGINFO("Error reading source fd (%s)\n", strerror(errno));
2277 goto exit;
2278 }
2279 if (write(dest_fd, buffer, bs) != bs) {
2280 LOGINFO("Error writing destination fd (%s)\n", strerror(errno));
2281 goto exit;
2282 }
2283 backedup_size += (unsigned long long)(bs);
Matt Mower029a82d2017-01-08 13:12:38 -06002284 Remain -= (unsigned long long)(bs);
bigbiffce8f83c2015-12-12 18:30:21 -05002285 if (part_settings->progress)
2286 part_settings->progress->UpdateSize(backedup_size);
Ethan Yonker472f5062016-02-25 13:47:30 -06002287 if (PartitionManager.Check_Backup_Cancel() != 0)
2288 goto exit;
2289 }
bigbiffce8f83c2015-12-12 18:30:21 -05002290 if (part_settings->progress)
2291 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker472f5062016-02-25 13:47:30 -06002292 fsync(dest_fd);
nailyka083dc62016-11-11 21:41:28 +01002293
2294 if (!part_settings->adbbackup && part_settings->PM_Method == PM_BACKUP) {
2295 tw_set_default_metadata(destfn.c_str());
2296 LOGINFO("Restored default metadata for %s\n", destfn.c_str());
2297 }
2298
Ethan Yonker472f5062016-02-25 13:47:30 -06002299 ret = true;
2300exit:
2301 if (src_fd >= 0)
2302 close(src_fd);
2303 if (dest_fd >= 0)
2304 close(dest_fd);
2305 if (buffer)
2306 free(buffer);
2307 return ret;
2308}
2309
bigbiffce8f83c2015-12-12 18:30:21 -05002310bool TWPartition::Backup_Dump_Image(PartitionSettings *part_settings) {
Vojtech Bocek05534202013-09-11 08:11:56 +02002311 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04002312
Ethan Yonker74db1572015-10-28 12:44:49 -05002313 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}"));
2314 gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002315
bigbiffce8f83c2015-12-12 18:30:21 -05002316 if (part_settings->progress)
2317 part_settings->progress->SetPartitionSize(Backup_Size);
Dees_Troy43d8b002012-09-17 16:00:01 -04002318
Ethan Yonker472f5062016-02-25 13:47:30 -06002319 Backup_FileName = Backup_Name + "." + Current_File_System + ".win";
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002320 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04002321
2322 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
bigbiffce8f83c2015-12-12 18:30:21 -05002323
Dees_Troy2673cec2013-04-02 20:22:16 +00002324 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02002325 TWFunc::Exec_Cmd(Command);
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06002326 tw_set_default_metadata(Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04002327 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
2328 // 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 -06002329 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName));
Dees_Troy7c2dec82012-09-26 09:49:14 -04002330 return false;
2331 }
bigbiffce8f83c2015-12-12 18:30:21 -05002332 if (part_settings->progress)
2333 part_settings->progress->UpdateSize(Backup_Size);
2334
Dees_Troy43d8b002012-09-17 16:00:01 -04002335 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002336}
2337
bigbiffce8f83c2015-12-12 18:30:21 -05002338unsigned long long TWPartition::Get_Restore_Size(PartitionSettings *part_settings) {
2339 if (!part_settings->adbbackup) {
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002340 InfoManager restore_info(part_settings->Backup_Folder + "/" + Backup_Name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -05002341 if (restore_info.LoadValues() == 0) {
2342 if (restore_info.GetValue("backup_size", Restore_Size) == 0) {
2343 LOGINFO("Read info file, restore size is %llu\n", Restore_Size);
2344 return Restore_Size;
2345 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002346 }
2347 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002348
Matt Mower029a82d2017-01-08 13:12:38 -06002349 string Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
2350 string Restore_File_System = Get_Restore_File_System(part_settings);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002351
2352 if (Is_Image(Restore_File_System)) {
2353 Restore_Size = TWFunc::Get_File_Size(Full_FileName);
2354 return Restore_Size;
2355 }
2356
2357 twrpTar tar;
2358 tar.setdir(Backup_Path);
2359 tar.setfn(Full_FileName);
bigbiffce8f83c2015-12-12 18:30:21 -05002360 tar.backup_name = Full_FileName;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002361#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2362 string Password;
2363 DataManager::GetValue("tw_restore_password", Password);
2364 if (!Password.empty())
2365 tar.setpassword(Password);
2366#endif
2367 tar.partition_name = Backup_Name;
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002368 tar.backup_folder = part_settings->Backup_Folder;
bigbiffce8f83c2015-12-12 18:30:21 -05002369 tar.part_settings = part_settings;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05002370 Restore_Size = tar.get_size();
2371 return Restore_Size;
2372}
2373
bigbiffce8f83c2015-12-12 18:30:21 -05002374bool TWPartition::Restore_Tar(PartitionSettings *part_settings) {
Ethan Yonker472f5062016-02-25 13:47:30 -06002375 string Full_FileName;
Dees Troy4159aed2014-02-28 17:24:43 +00002376 bool ret = false;
bigbiffce8f83c2015-12-12 18:30:21 -05002377 string Restore_File_System = Get_Restore_File_System(part_settings);
Dees_Troy43d8b002012-09-17 16:00:01 -04002378
Dees_Troye58d5262012-09-21 12:27:57 -04002379 if (Has_Android_Secure) {
Dees_Troye58d5262012-09-21 12:27:57 -04002380 if (!Wipe_AndSec())
2381 return false;
Gary Peck43acadf2012-11-21 21:19:01 -08002382 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -05002383 gui_msg(Msg("wiping=Wiping {1}")(Backup_Display_Name));
Ethan Yonker5eac2222014-06-11 12:22:55 -05002384 if (Has_Data_Media && Mount_Point == "/data" && Restore_File_System != Current_File_System) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002385 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 -05002386 if (!Wipe_Data_Without_Wiping_Media())
2387 return false;
2388 } else {
2389 if (!Wipe(Restore_File_System))
2390 return false;
2391 }
Dees_Troye58d5262012-09-21 12:27:57 -04002392 }
Matt Mower3c366972015-12-25 19:28:31 -06002393 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002394 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
Dees_Troy43d8b002012-09-17 16:00:01 -04002395
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002396 // Remount as read/write as needed so we can restore the backup
2397 if (!ReMount_RW(true))
Dees_Troy43d8b002012-09-17 16:00:01 -04002398 return false;
2399
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002400 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker87af5632014-02-10 11:56:35 -06002401 twrpTar tar;
bigbiffce8f83c2015-12-12 18:30:21 -05002402 tar.part_settings = part_settings;
Ethan Yonker87af5632014-02-10 11:56:35 -06002403 tar.setdir(Backup_Path);
2404 tar.setfn(Full_FileName);
2405 tar.backup_name = Backup_Name;
2406#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
2407 string Password;
2408 DataManager::GetValue("tw_restore_password", Password);
2409 if (!Password.empty())
2410 tar.setpassword(Password);
2411#endif
bigbiffce8f83c2015-12-12 18:30:21 -05002412 part_settings->progress->SetPartitionSize(Get_Restore_Size(part_settings));
2413 if (tar.extractTarFork() != 0)
Dees Troy4159aed2014-02-28 17:24:43 +00002414 ret = false;
2415 else
2416 ret = true;
2417#ifdef HAVE_CAPABILITIES
2418 // Restore capabilities to the run-as binary
2419 if (Mount_Point == "/system" && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
2420 struct vfs_cap_data cap_data;
2421 uint64_t capabilities = (1 << CAP_SETUID) | (1 << CAP_SETGID);
2422
2423 memset(&cap_data, 0, sizeof(cap_data));
2424 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
2425 cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
2426 cap_data.data[0].inheritable = 0;
2427 cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
2428 cap_data.data[1].inheritable = 0;
2429 if (setxattr("/system/bin/run-as", XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
2430 LOGINFO("Failed to reset capabilities of /system/bin/run-as binary.\n");
2431 } else {
2432 LOGINFO("Reset capabilities of /system/bin/run-as binary successful.\n");
2433 }
2434 }
2435#endif
James Christopher Adduonod6f94ac2016-02-29 04:26:04 -05002436 if (Mount_Read_Only || Mount_Flags & MS_RDONLY)
2437 // Remount as read only when restoration is complete
2438 ReMount(true);
2439
Dees Troy4159aed2014-02-28 17:24:43 +00002440 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04002441}
2442
bigbiffce8f83c2015-12-12 18:30:21 -05002443bool TWPartition::Restore_Image(PartitionSettings *part_settings) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002444 string Full_FileName;
bigbiffce8f83c2015-12-12 18:30:21 -05002445 string Restore_File_System = Get_Restore_File_System(part_settings);
Dees_Troy43d8b002012-09-17 16:00:01 -04002446
Matt Mower3c366972015-12-25 19:28:31 -06002447 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}"));
Ethan Yonker74db1572015-10-28 12:44:49 -05002448 gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name));
bigbiffce8f83c2015-12-12 18:30:21 -05002449
2450 if (part_settings->adbbackup)
2451 Full_FileName = TW_ADB_RESTORE;
2452 else
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002453 Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
Gary Peck15e623d2012-11-21 21:07:58 -08002454
Ethan Yonker96af84a2015-01-05 14:58:36 -06002455 if (Restore_File_System == "emmc") {
bigbiffce8f83c2015-12-12 18:30:21 -05002456 if (!part_settings->adbbackup)
2457 part_settings->total_restore_size = (uint64_t)(TWFunc::Get_File_Size(Full_FileName));
2458 if (!Raw_Read_Write(part_settings))
Ethan Yonker96af84a2015-01-05 14:58:36 -06002459 return false;
2460 } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") {
bigbiffce8f83c2015-12-12 18:30:21 -05002461 if (!Flash_Image_FI(Full_FileName, part_settings->progress))
2462 return false;
2463 }
2464
2465 if (part_settings->adbbackup) {
2466 if (!twadbbu::Write_TWEOF())
Ethan Yonker96af84a2015-01-05 14:58:36 -06002467 return false;
Gary Peck15e623d2012-11-21 21:07:58 -08002468 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002469 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04002470}
Dees_Troy5bf43922012-09-07 16:07:55 -04002471
2472bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy0550cfb2012-10-13 11:56:13 -04002473 bool ret = false, Was_Already_Mounted = false;
Dees_Troy51127312012-09-08 13:08:49 -04002474
Ethan Yonker1b190162016-12-05 15:25:19 -06002475 Find_Actual_Block_Device();
2476
2477 if (!Can_Be_Mounted && !Is_Encrypted) {
2478 if (TWFunc::Path_Exists(Actual_Block_Device) && Find_Partition_Size()) {
2479 Used = Size;
2480 Backup_Size = Size;
2481 return true;
2482 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002483 return false;
Ethan Yonker1b190162016-12-05 15:25:19 -06002484 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002485
Dees_Troy0550cfb2012-10-13 11:56:13 -04002486 Was_Already_Mounted = Is_Mounted();
Dees_Troy38bd7602012-09-14 13:33:53 -04002487 if (Removable || Is_Encrypted) {
2488 if (!Mount(false))
2489 return true;
2490 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04002491 return false;
Dees_Troy51127312012-09-08 13:08:49 -04002492
2493 ret = Get_Size_Via_statfs(Display_Error);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002494 if (!ret || Size == 0) {
2495 if (!Get_Size_Via_df(Display_Error)) {
2496 if (!Was_Already_Mounted)
2497 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -04002498 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002499 }
2500 }
Dees_Troy51127312012-09-08 13:08:49 -04002501
Dees_Troy5bf43922012-09-07 16:07:55 -04002502 if (Has_Data_Media) {
2503 if (Mount(Display_Error)) {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002504 Used = backup_exclusions.Get_Folder_Size(Mount_Point);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002505 Backup_Size = Used;
2506 int bak = (int)(Used / 1048576LLU);
Dees_Troy51127312012-09-08 13:08:49 -04002507 int fre = (int)(Free / 1048576LLU);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002508 LOGINFO("Data backup size is %iMB, free: %iMB.\n", bak, fre);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002509 } else {
2510 if (!Was_Already_Mounted)
2511 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002512 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002513 }
Dees_Troye58d5262012-09-21 12:27:57 -04002514 } else if (Has_Android_Secure) {
2515 if (Mount(Display_Error))
Ethan Yonker3fdcda42016-11-30 12:29:37 -06002516 Backup_Size = backup_exclusions.Get_Folder_Size(Backup_Path);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002517 else {
2518 if (!Was_Already_Mounted)
2519 UnMount(false);
Dees_Troye58d5262012-09-21 12:27:57 -04002520 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002521 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002522 }
Dees_Troy0550cfb2012-10-13 11:56:13 -04002523 if (!Was_Already_Mounted)
2524 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002525 return true;
Dees_Troy51127312012-09-08 13:08:49 -04002526}
Dees_Troy38bd7602012-09-14 13:33:53 -04002527
2528void TWPartition::Find_Actual_Block_Device(void) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04002529 if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002530 Actual_Block_Device = Decrypted_Block_Device;
Ethan Yonker1b190162016-12-05 15:25:19 -06002531 if (TWFunc::Path_Exists(Decrypted_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002532 Is_Present = true;
Ethan Yonker1b190162016-12-05 15:25:19 -06002533 return;
2534 }
2535 } else if (SlotSelect && TWFunc::Path_Exists(Primary_Block_Device + PartitionManager.Get_Active_Slot_Suffix())) {
2536 Actual_Block_Device = Primary_Block_Device + PartitionManager.Get_Active_Slot_Suffix();
2537 unlink(Primary_Block_Device.c_str());
2538 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
2539 Is_Present = true;
2540 return;
Dees_Troy43d8b002012-09-17 16:00:01 -04002541 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002542 Is_Present = true;
2543 Actual_Block_Device = Primary_Block_Device;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002544 return;
2545 }
Ethan Yonker1b190162016-12-05 15:25:19 -06002546 if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy3f04d032012-10-07 18:20:09 -04002547 Actual_Block_Device = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -04002548 Is_Present = true;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002549 } else {
Dees_Troy38bd7602012-09-14 13:33:53 -04002550 Is_Present = false;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002551 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002552}
2553
2554void TWPartition::Recreate_Media_Folder(void) {
2555 string Command;
Ethan Yonker66a19492015-12-10 10:19:45 -06002556 string Media_Path = Mount_Point + "/media";
Dees_Troy38bd7602012-09-14 13:33:53 -04002557
Ethan Yonkerbd7492d2016-12-07 13:55:01 -06002558 if (Is_FBE) {
2559 LOGINFO("Not recreating media folder on FBE\n");
2560 return;
2561 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002562 if (!Mount(true)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002563 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Media_Path));
2564 } else if (!TWFunc::Path_Exists(Media_Path)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002565 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker66a19492015-12-10 10:19:45 -06002566 LOGINFO("Recreating %s folder.\n", Media_Path.c_str());
2567 mkdir(Media_Path.c_str(), 0770);
xiaolu9416f4f2015-06-04 08:22:23 +08002568 string Internal_path = DataManager::GetStrValue("tw_internal_path");
2569 if (!Internal_path.empty()) {
2570 LOGINFO("Recreating %s folder.\n", Internal_path.c_str());
2571 mkdir(Internal_path.c_str(), 0770);
2572 }
2573#ifdef TW_INTERNAL_STORAGE_PATH
2574 mkdir(EXPAND(TW_INTERNAL_STORAGE_PATH), 0770);
2575#endif
Matt Mower87413642017-01-17 21:14:46 -06002576
thata3d31fb2014-12-21 22:27:40 +01002577 // Afterwards, we will try to set the
2578 // default metadata that we were hopefully able to get during
2579 // early boot.
Ethan Yonker66a19492015-12-10 10:19:45 -06002580 tw_set_default_metadata(Media_Path.c_str());
xiaolu9416f4f2015-06-04 08:22:23 +08002581 if (!Internal_path.empty())
2582 tw_set_default_metadata(Internal_path.c_str());
Matt Mower87413642017-01-17 21:14:46 -06002583
Ethan Yonker5eac2222014-06-11 12:22:55 -05002584 // Toggle mount to ensure that "internal sdcard" gets mounted
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002585 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker5eac2222014-06-11 12:22:55 -05002586 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy38bd7602012-09-14 13:33:53 -04002587 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002588}
Dees_Troye58d5262012-09-21 12:27:57 -04002589
2590void TWPartition::Recreate_AndSec_Folder(void) {
Dees_Troye58d5262012-09-21 12:27:57 -04002591 if (!Has_Android_Secure)
2592 return;
Dees_Troy2673cec2013-04-02 20:22:16 +00002593 LOGINFO("Creating %s: %s\n", Backup_Display_Name.c_str(), Symlink_Path.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04002594 if (!Mount(true)) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002595 gui_msg(Msg(msg::kError, "recreate_folder_err=Unable to recreate {1} folder.")(Backup_Name));
Dees_Troye58d5262012-09-21 12:27:57 -04002596 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002597 LOGINFO("Recreating %s folder.\n", Backup_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002598 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05002599 mkdir(Symlink_Path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002600 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002601 }
2602}
bigbiff7cb4c332014-11-26 20:36:07 -05002603
2604uint64_t TWPartition::Get_Max_FileSize() {
2605 uint64_t maxFileSize = 0;
2606 const uint64_t constGB = (uint64_t) 1024 * 1024 * 1024;
2607 const uint64_t constTB = (uint64_t) constGB * 1024;
2608 const uint64_t constPB = (uint64_t) constTB * 1024;
bigbiff0c532032014-12-21 13:41:26 -05002609 if (Current_File_System == "ext4")
2610 maxFileSize = 16 * constTB; //16 TB
2611 else if (Current_File_System == "vfat")
2612 maxFileSize = 4 * constGB; //4 GB
2613 else if (Current_File_System == "ntfs")
2614 maxFileSize = 256 * constTB; //256 TB
2615 else if (Current_File_System == "exfat")
2616 maxFileSize = 16 * constPB; //16 PB
2617 else if (Current_File_System == "ext3")
2618 maxFileSize = 2 * constTB; //2 TB
2619 else if (Current_File_System == "f2fs")
2620 maxFileSize = 3.94 * constTB; //3.94 TB
bigbiff7cb4c332014-11-26 20:36:07 -05002621 else
2622 maxFileSize = 100000000L;
2623 return maxFileSize - 1;
2624}
2625
bigbiffce8f83c2015-12-12 18:30:21 -05002626bool TWPartition::Flash_Image(PartitionSettings *part_settings) {
2627 string Restore_File_System, full_filename;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002628
Ethan Yonkere080c1f2016-09-19 13:50:25 -05002629 full_filename = part_settings->Backup_Folder + "/" + Backup_FileName;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002630
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002631 LOGINFO("Image filename is: %s\n", Backup_FileName.c_str());
bigbiffce8f83c2015-12-12 18:30:21 -05002632
2633 if (Backup_Method == BM_FILES) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002634 LOGERR("Cannot flash images to file systems\n");
2635 return false;
2636 } else if (!Can_Flash_Img) {
2637 LOGERR("Cannot flash images to partitions %s\n", Display_Name.c_str());
2638 return false;
2639 } else {
2640 if (!Find_Partition_Size()) {
2641 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
2642 return false;
2643 }
bigbiffce8f83c2015-12-12 18:30:21 -05002644 unsigned long long image_size = TWFunc::Get_File_Size(full_filename);
Ethan Yonker96af84a2015-01-05 14:58:36 -06002645 if (image_size > Size) {
Ethan Yonker74db1572015-10-28 12:44:49 -05002646 LOGINFO("Size (%llu bytes) of image '%s' is larger than target device '%s' (%llu bytes)\n",
Ethan Yonkerdcf2b672016-09-13 14:41:53 -05002647 image_size, Backup_FileName.c_str(), Actual_Block_Device.c_str(), Size);
Ethan Yonker74db1572015-10-28 12:44:49 -05002648 gui_err("img_size_err=Size of image is larger than target device");
Ethan Yonker96af84a2015-01-05 14:58:36 -06002649 return false;
2650 }
bigbiffce8f83c2015-12-12 18:30:21 -05002651 if (Backup_Method == BM_DD) {
2652 if (!part_settings->adbbackup) {
2653 if (Is_Sparse_Image(full_filename)) {
2654 return Flash_Sparse_Image(full_filename);
2655 }
Ethan Yonker472f5062016-02-25 13:47:30 -06002656 }
bigbiffce8f83c2015-12-12 18:30:21 -05002657 return Raw_Read_Write(part_settings);
2658 } else if (Backup_Method == BM_FLASH_UTILS) {
2659 return Flash_Image_FI(full_filename, NULL);
Ethan Yonker472f5062016-02-25 13:47:30 -06002660 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002661 }
2662
2663 LOGERR("Unknown flash method for '%s'\n", Mount_Point.c_str());
2664 return false;
2665}
2666
Ethan Yonker472f5062016-02-25 13:47:30 -06002667bool TWPartition::Is_Sparse_Image(const string& Filename) {
HashBanged974bb2016-01-30 14:20:09 -05002668 uint32_t magic = 0;
2669 int fd = open(Filename.c_str(), O_RDONLY);
2670 if (fd < 0) {
2671 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2672 return false;
2673 }
bigbiffce8f83c2015-12-12 18:30:21 -05002674
HashBanged974bb2016-01-30 14:20:09 -05002675 if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) {
2676 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno)));
2677 close(fd);
2678 return false;
2679 }
2680 close(fd);
Ethan Yonker472f5062016-02-25 13:47:30 -06002681 if (magic == SPARSE_HEADER_MAGIC)
2682 return true;
2683 return false;
2684}
2685
2686bool TWPartition::Flash_Sparse_Image(const string& Filename) {
2687 string Command;
2688
2689 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
2690
2691 Command = "simg2img '" + Filename + "' '" + Actual_Block_Device + "'";
Ethan Yonker96af84a2015-01-05 14:58:36 -06002692 LOGINFO("Flash command: '%s'\n", Command.c_str());
2693 TWFunc::Exec_Cmd(Command);
2694 return true;
2695}
2696
Ethan Yonker472f5062016-02-25 13:47:30 -06002697bool TWPartition::Flash_Image_FI(const string& Filename, ProgressTracking *progress) {
Ethan Yonker96af84a2015-01-05 14:58:36 -06002698 string Command;
Ethan Yonker472f5062016-02-25 13:47:30 -06002699 unsigned long long file_size;
Ethan Yonker96af84a2015-01-05 14:58:36 -06002700
Ethan Yonker74db1572015-10-28 12:44:49 -05002701 gui_msg(Msg("flashing=Flashing {1}...")(Display_Name));
Ethan Yonker472f5062016-02-25 13:47:30 -06002702 if (progress) {
2703 file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename));
2704 progress->SetPartitionSize(file_size);
2705 }
Ethan Yonker96af84a2015-01-05 14:58:36 -06002706 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
2707 Command = "erase_image " + MTD_Name;
2708 LOGINFO("Erase command: '%s'\n", Command.c_str());
2709 TWFunc::Exec_Cmd(Command);
2710 Command = "flash_image " + MTD_Name + " '" + Filename + "'";
2711 LOGINFO("Flash command: '%s'\n", Command.c_str());
2712 TWFunc::Exec_Cmd(Command);
Ethan Yonker472f5062016-02-25 13:47:30 -06002713 if (progress)
2714 progress->UpdateSize(file_size);
Ethan Yonker96af84a2015-01-05 14:58:36 -06002715 return true;
2716}
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05002717
2718void TWPartition::Change_Mount_Read_Only(bool new_value) {
2719 Mount_Read_Only = new_value;
2720}
2721
bigbiffce8f83c2015-12-12 18:30:21 -05002722bool TWPartition::Is_Read_Only() {
2723 return Mount_Read_Only;
2724}
2725
Ethan Yonkereb32b1f2015-05-18 10:23:03 -05002726int TWPartition::Check_Lifetime_Writes() {
2727 bool original_read_only = Mount_Read_Only;
2728 int ret = 1;
2729
2730 Mount_Read_Only = true;
2731 if (Mount(false)) {
2732 Find_Actual_Block_Device();
2733 string block = basename(Actual_Block_Device.c_str());
2734 string file = "/sys/fs/" + Current_File_System + "/" + block + "/lifetime_write_kbytes";
2735 string result;
2736 if (TWFunc::Path_Exists(file)) {
2737 if (TWFunc::read_file(file, result) != 0) {
2738 LOGINFO("Check_Lifetime_Writes of '%s' failed to read_file\n", file.c_str());
2739 } else {
2740 LOGINFO("Check_Lifetime_Writes result: '%s'\n", result.c_str());
2741 if (result == "0") {
2742 ret = 0;
2743 }
2744 }
2745 } else {
2746 LOGINFO("Check_Lifetime_Writes file does not exist '%s'\n", file.c_str());
2747 }
2748 UnMount(true);
2749 } else {
2750 LOGINFO("Check_Lifetime_Writes failed to mount '%s'\n", Mount_Point.c_str());
2751 }
2752 Mount_Read_Only = original_read_only;
2753 return ret;
2754}
Ethan Yonker66a19492015-12-10 10:19:45 -06002755
2756int TWPartition::Decrypt_Adopted() {
2757#ifdef TW_INCLUDE_CRYPTO
2758 int ret = 1;
2759 Is_Adopted_Storage = false;
2760 string Adopted_Key_File = "";
2761
2762 if (!Removable)
2763 return ret;
2764
2765 int fd = open(Alternate_Block_Device.c_str(), O_RDONLY);
2766 if (fd < 0) {
2767 LOGINFO("failed to open '%s'\n", Alternate_Block_Device.c_str());
2768 return ret;
2769 }
2770 char type_guid[80];
2771 char part_guid[80];
2772
2773 if (gpt_disk_get_partition_info(fd, 2, type_guid, part_guid) == 0) {
2774 LOGINFO("type: '%s'\n", type_guid);
2775 LOGINFO("part: '%s'\n", part_guid);
2776 Adopted_GUID = part_guid;
2777 LOGINFO("Adopted_GUID '%s'\n", Adopted_GUID.c_str());
2778 if (strcmp(type_guid, TWGptAndroidExpand) == 0) {
2779 LOGINFO("android_expand found\n");
2780 Adopted_Key_File = "/data/misc/vold/expand_";
2781 Adopted_Key_File += part_guid;
2782 Adopted_Key_File += ".key";
2783 if (TWFunc::Path_Exists(Adopted_Key_File)) {
2784 Is_Adopted_Storage = true;
2785 /* Until we find a use case for this, I think it is safe
2786 * to disable USB Mass Storage whenever adopted storage
2787 * is present.
2788 */
2789 LOGINFO("Detected adopted storage, disabling USB mass storage mode\n");
2790 DataManager::SetValue("tw_has_usb_storage", 0);
2791 }
2792 }
2793 }
2794
2795 if (Is_Adopted_Storage) {
2796 string Adopted_Block_Device = Alternate_Block_Device + "p2";
2797 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
2798 Adopted_Block_Device = Alternate_Block_Device + "2";
2799 if (!TWFunc::Path_Exists(Adopted_Block_Device)) {
2800 LOGINFO("Adopted block device does not exist\n");
2801 goto exit;
2802 }
2803 }
2804 LOGINFO("key file is '%s', block device '%s'\n", Adopted_Key_File.c_str(), Adopted_Block_Device.c_str());
2805 char crypto_blkdev[MAXPATHLEN];
2806 std::string thekey;
2807 int fdkey = open(Adopted_Key_File.c_str(), O_RDONLY);
2808 if (fdkey < 0) {
2809 LOGINFO("failed to open key file\n");
2810 goto exit;
2811 }
2812 char buf[512];
2813 ssize_t n;
2814 while ((n = read(fdkey, &buf[0], sizeof(buf))) > 0) {
2815 thekey.append(buf, n);
2816 }
2817 close(fdkey);
2818 unsigned char* key = (unsigned char*) thekey.data();
2819 cryptfs_revert_ext_volume(part_guid);
2820
2821 ret = cryptfs_setup_ext_volume(part_guid, Adopted_Block_Device.c_str(), key, thekey.size(), crypto_blkdev);
2822 if (ret == 0) {
2823 LOGINFO("adopted storage new block device: '%s'\n", crypto_blkdev);
2824 Decrypted_Block_Device = crypto_blkdev;
2825 Is_Decrypted = true;
2826 Is_Encrypted = true;
2827 Find_Actual_Block_Device();
Kjell Braden3126a112016-06-19 16:58:15 +00002828 if (!Mount_Storage_Retry(false)) {
Ethan Yonker66a19492015-12-10 10:19:45 -06002829 LOGERR("Failed to mount decrypted adopted storage device\n");
2830 Is_Decrypted = false;
2831 Is_Encrypted = false;
2832 cryptfs_revert_ext_volume(part_guid);
2833 ret = 1;
2834 } else {
Ethan Yonkerfcf3f242016-02-16 12:30:26 -06002835 UnMount(false);
2836 Has_Android_Secure = false;
2837 Symlink_Path = "";
2838 Symlink_Mount_Point = "";
2839 Backup_Name = Mount_Point.substr(1);
2840 Backup_Path = Mount_Point;
2841 TWPartition* sdext = PartitionManager.Find_Partition_By_Path("/sd-ext");
2842 if (sdext && sdext->Actual_Block_Device == Adopted_Block_Device) {
2843 LOGINFO("Removing /sd-ext from partition list due to adopted storage\n");
2844 PartitionManager.Remove_Partition_By_Path("/sd-ext");
2845 }
Ethan Yonker66a19492015-12-10 10:19:45 -06002846 Setup_Data_Media();
2847 Recreate_Media_Folder();
2848 Wipe_Available_in_GUI = true;
2849 Wipe_During_Factory_Reset = true;
2850 Can_Be_Backed_Up = true;
2851 Can_Encrypt_Backup = true;
2852 Use_Userdata_Encryption = true;
2853 Is_Storage = true;
2854 Storage_Name = "Adopted Storage";
2855 Is_SubPartition = true;
2856 SubPartition_Of = "/data";
2857 PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
2858 DataManager::SetValue("tw_has_adopted_storage", 1);
2859 }
2860 } else {
2861 LOGERR("Failed to setup adopted storage decryption\n");
2862 }
2863 }
2864exit:
Matt Mower06543e32017-01-06 15:25:26 -06002865 close(fd);
Ethan Yonker66a19492015-12-10 10:19:45 -06002866 return ret;
2867#else
2868 LOGINFO("Decrypt_Adopted: no crypto support\n");
2869 return 1;
2870#endif
2871}
2872
2873void TWPartition::Revert_Adopted() {
2874#ifdef TW_INCLUDE_CRYPTO
2875 if (!Adopted_GUID.empty()) {
2876 PartitionManager.Remove_MTP_Storage(Mount_Point);
2877 UnMount(false);
2878 cryptfs_revert_ext_volume(Adopted_GUID.c_str());
2879 Is_Adopted_Storage = false;
2880 Is_Encrypted = false;
2881 Is_Decrypted = false;
2882 Decrypted_Block_Device = "";
2883 Find_Actual_Block_Device();
2884 Wipe_During_Factory_Reset = false;
2885 Can_Be_Backed_Up = false;
2886 Can_Encrypt_Backup = false;
2887 Use_Userdata_Encryption = false;
2888 Is_SubPartition = false;
2889 SubPartition_Of = "";
2890 Has_Data_Media = false;
2891 Storage_Path = Mount_Point;
2892 if (!Symlink_Mount_Point.empty()) {
2893 TWPartition* Dat = PartitionManager.Find_Partition_By_Path("/data");
2894 if (Dat) {
2895 Dat->UnMount(false);
2896 Dat->Symlink_Mount_Point = Symlink_Mount_Point;
2897 }
2898 Symlink_Mount_Point = "";
2899 }
2900 }
2901#else
2902 LOGINFO("Revert_Adopted: no crypto support\n");
2903#endif
2904}
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04002905
2906void TWPartition::Set_Backup_FileName(string fname) {
2907 Backup_FileName = fname;
2908}
2909
2910string TWPartition::Get_Backup_Name() {
2911 return Backup_Name;
2912}