blob: f1d7fd2a93ccac410b114ca2b20c8934b2fc08e2 [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002 Copyright 2013 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>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050027#include <iostream>
28#include <sstream>
Dees_Troy51a0e822012-09-05 15:24:24 -040029
Dees_Troy657c3092012-09-10 20:32:10 -040030#ifdef TW_INCLUDE_CRYPTO
31 #include "cutils/properties.h"
32#endif
33
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050034#include "libblkid/blkid.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040035#include "variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000036#include "twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040037#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040038#include "data.hpp"
Dees_Troy43d8b002012-09-17 16:00:01 -040039#include "twrp-functions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050040#include "twrpDigest.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050041#include "twrpTar.hpp"
bigbiff bigbiff34684ff2013-12-01 21:03:45 -050042#include "twrpDU.hpp"
bigbiff bigbiff6b600f92014-01-05 18:13:43 -050043#include "fixPermissions.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050044#include "infomanager.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040045extern "C" {
Dees_Troy38bd7602012-09-14 13:33:53 -040046 #include "mtdutils/mtdutils.h"
47 #include "mtdutils/mounts.h"
Dees_Troy85f44ed2013-01-09 18:42:36 +000048#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
49 #include "crypto/libcrypt_samsung/include/libcrypt_samsung.h"
50#endif
Dees_Troya95f55c2013-08-17 13:14:43 +000051#ifdef USE_EXT4
52 #include "make_ext4fs.h"
53#endif
Ethan Yonker71413f42014-02-26 13:36:08 -060054
55#ifdef TW_INCLUDE_CRYPTO
56 #ifdef TW_INCLUDE_JB_CRYPTO
57 #include "crypto/jb/cryptfs.h"
58 #else
59 #include "crypto/ics/cryptfs.h"
60 #endif
61#endif
Dees_Troy5bf43922012-09-07 16:07:55 -040062}
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040063#ifdef HAVE_SELINUX
64#include "selinux/selinux.h"
Ethan Yonkerf27497f2014-02-09 11:48:33 -060065#include <selinux/label.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040066#endif
Dees Troy4159aed2014-02-28 17:24:43 +000067#ifdef HAVE_CAPABILITIES
68#include <sys/capability.h>
69#include <sys/xattr.h>
70#include <linux/xattr.h>
71#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040072
bigbiff bigbiff9c754052013-01-09 09:09:08 -050073using namespace std;
74
Dees_Troya95f55c2013-08-17 13:14:43 +000075extern struct selabel_handle *selinux_handle;
76
Hashcode62bd9e02013-11-19 21:59:42 -080077struct flag_list {
78 const char *name;
79 unsigned flag;
80};
81
82static struct flag_list mount_flags[] = {
83 { "noatime", MS_NOATIME },
84 { "noexec", MS_NOEXEC },
85 { "nosuid", MS_NOSUID },
86 { "nodev", MS_NODEV },
87 { "nodiratime", MS_NODIRATIME },
88 { "ro", MS_RDONLY },
89 { "rw", 0 },
90 { "remount", MS_REMOUNT },
91 { "bind", MS_BIND },
92 { "rec", MS_REC },
Dees Troyc4bc30e2014-02-03 15:04:19 +000093#ifdef MS_UNBINDABLE
Hashcode62bd9e02013-11-19 21:59:42 -080094 { "unbindable", MS_UNBINDABLE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000095#endif
96#ifdef MS_PRIVATE
Hashcode62bd9e02013-11-19 21:59:42 -080097 { "private", MS_PRIVATE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000098#endif
99#ifdef MS_SLAVE
Hashcode62bd9e02013-11-19 21:59:42 -0800100 { "slave", MS_SLAVE },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000101#endif
102#ifdef MS_SHARED
Hashcode62bd9e02013-11-19 21:59:42 -0800103 { "shared", MS_SHARED },
Dees Troyc4bc30e2014-02-03 15:04:19 +0000104#endif
Hashcode62bd9e02013-11-19 21:59:42 -0800105 { "sync", MS_SYNCHRONOUS },
106 { "defaults", 0 },
107 { 0, 0 },
108};
109
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400110TWPartition::TWPartition(int *id) {
111 initmtpid = id;
Dees_Troy51a0e822012-09-05 15:24:24 -0400112 Can_Be_Mounted = false;
113 Can_Be_Wiped = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500114 Can_Be_Backed_Up = false;
Vojtech Bocek1dc30982013-08-30 21:49:30 +0200115 Use_Rm_Rf = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400116 Wipe_During_Factory_Reset = false;
117 Wipe_Available_in_GUI = false;
118 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -0400119 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400120 SubPartition_Of = "";
121 Symlink_Path = "";
122 Symlink_Mount_Point = "";
123 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -0400124 Backup_Path = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400125 Actual_Block_Device = "";
126 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400127 Alternate_Block_Device = "";
128 Removable = false;
129 Is_Present = false;
130 Length = 0;
131 Size = 0;
132 Used = 0;
133 Free = 0;
134 Backup_Size = 0;
135 Can_Be_Encrypted = false;
136 Is_Encrypted = false;
137 Is_Decrypted = false;
138 Decrypted_Block_Device = "";
139 Display_Name = "";
Dees_Troya13d74f2013-03-24 08:54:55 -0500140 Backup_Display_Name = "";
141 Storage_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400142 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -0400143 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400144 MTD_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400145 Backup_Method = NONE;
Dees_Troy83bd4832013-05-04 12:39:56 +0000146 Can_Encrypt_Backup = false;
147 Use_Userdata_Encryption = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400148 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -0400149 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400150 Is_Storage = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500151 Is_Settings_Storage = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400152 Storage_Path = "";
153 Current_File_System = "";
154 Fstab_File_System = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800155 Mount_Flags = 0;
156 Mount_Options = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400157 Format_Block_Size = 0;
Dees_Troy68cab492012-12-12 19:29:35 +0000158 Ignore_Blkid = false;
Dees_Troy16c2b312013-01-15 16:51:18 +0000159 Retain_Layout_Version = false;
Dees_Troy85f44ed2013-01-09 18:42:36 +0000160#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
161 EcryptFS_Password = "";
162#endif
Dees_Troy51a0e822012-09-05 15:24:24 -0400163}
164
165TWPartition::~TWPartition(void) {
166 // Do nothing
167}
168
Dees_Troy5bf43922012-09-07 16:07:55 -0400169bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
170 char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH];
171 int line_len = Line.size(), index = 0, item_index = 0;
172 char* ptr;
Dees_Troy51127312012-09-08 13:08:49 -0400173 string Flags;
Dees_Troy5bf43922012-09-07 16:07:55 -0400174 strncpy(full_line, Line.c_str(), line_len);
Dees_Troya13d74f2013-03-24 08:54:55 -0500175 bool skip = false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400176
Dees_Troy51127312012-09-08 13:08:49 -0400177 for (index = 0; index < line_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500178 if (full_line[index] == 34)
179 skip = !skip;
180 if (!skip && full_line[index] <= 32)
Dees_Troy5bf43922012-09-07 16:07:55 -0400181 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400182 }
Dees_Troy7c2dec82012-09-26 09:49:14 -0400183 Mount_Point = full_line;
Dees_Troy2673cec2013-04-02 20:22:16 +0000184 LOGINFO("Processing '%s'\n", Mount_Point.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -0400185 Backup_Path = Mount_Point;
Dees_Troya13d74f2013-03-24 08:54:55 -0500186 Storage_Path = Mount_Point;
Dees_Troy70737fa2013-04-08 13:19:20 +0000187 Display_Name = full_line + 1;
188 Backup_Display_Name = Display_Name;
189 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400190 index = Mount_Point.size();
191 while (index < line_len) {
192 while (index < line_len && full_line[index] == '\0')
193 index++;
194 if (index >= line_len)
195 continue;
196 ptr = full_line + index;
197 if (item_index == 0) {
198 // File System
199 Fstab_File_System = ptr;
200 Current_File_System = ptr;
201 item_index++;
202 } else if (item_index == 1) {
203 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400204 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
Dees_Troy094207a2012-09-26 12:00:39 -0400205 MTD_Name = ptr;
206 Find_MTD_Block_Device(MTD_Name);
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400207 } else if (Fstab_File_System == "bml") {
208 if (Mount_Point == "/boot")
209 MTD_Name = "boot";
210 else if (Mount_Point == "/recovery")
211 MTD_Name = "recovery";
212 Primary_Block_Device = ptr;
213 if (*ptr != '/')
Dees_Troy2673cec2013-04-02 20:22:16 +0000214 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 -0400215 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400216 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000217 LOGERR("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400218 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000219 LOGINFO("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400220 return 0;
Dees_Troy38bd7602012-09-14 13:33:53 -0400221 } else {
222 Primary_Block_Device = ptr;
223 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400224 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400225 item_index++;
226 } else if (item_index > 1) {
227 if (*ptr == '/') {
228 // Alternate Block Device
229 Alternate_Block_Device = ptr;
230 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
231 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
232 // Partition length
233 ptr += 7;
234 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400235 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
236 // Custom flags, save for later so that new values aren't overwritten by defaults
237 ptr += 6;
238 Flags = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000239 Process_Flags(Flags, Display_Error);
Dees_Troy38bd7602012-09-14 13:33:53 -0400240 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
241 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400242 } else {
243 // Unhandled data
Dees_Troy2673cec2013-04-02 20:22:16 +0000244 LOGINFO("Unhandled fstab information: '%s', %i, line: '%s'\n", ptr, index, Line.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400245 }
246 }
247 while (index < line_len && full_line[index] != '\0')
248 index++;
249 }
250
251 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
252 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000253 LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400254 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000255 LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400256 return 0;
257 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400258 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400259 Setup_File_System(Display_Error);
260 if (Mount_Point == "/system") {
261 Display_Name = "System";
Dees_Troya13d74f2013-03-24 08:54:55 -0500262 Backup_Display_Name = Display_Name;
263 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400264 Wipe_Available_in_GUI = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500265 Can_Be_Backed_Up = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400266 } else if (Mount_Point == "/data") {
267 Display_Name = "Data";
Dees_Troya13d74f2013-03-24 08:54:55 -0500268 Backup_Display_Name = Display_Name;
269 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400270 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400271 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500272 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000273 Can_Encrypt_Backup = true;
274 Use_Userdata_Encryption = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400275#ifdef RECOVERY_SDCARD_ON_DATA
Dees_Troya13d74f2013-03-24 08:54:55 -0500276 Storage_Name = "Internal Storage";
Dees_Troy5bf43922012-09-07 16:07:55 -0400277 Has_Data_Media = true;
Dees_Troy51127312012-09-08 13:08:49 -0400278 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500279 Is_Settings_Storage = true;
Dees_Troy51127312012-09-08 13:08:49 -0400280 Storage_Path = "/data/media";
Dees_Troy16b74352012-11-14 22:27:31 +0000281 Symlink_Path = Storage_Path;
Dees_Troy657c3092012-09-10 20:32:10 -0400282 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
283 Make_Dir("/emmc", Display_Error);
Dees_Troy657c3092012-09-10 20:32:10 -0400284 Symlink_Mount_Point = "/emmc";
285 } else {
286 Make_Dir("/sdcard", Display_Error);
Dees_Troy657c3092012-09-10 20:32:10 -0400287 Symlink_Mount_Point = "/sdcard";
288 }
Dees_Troy16b74352012-11-14 22:27:31 +0000289 if (Mount(false) && TWFunc::Path_Exists("/data/media/0")) {
290 Storage_Path = "/data/media/0";
291 Symlink_Path = Storage_Path;
292 DataManager::SetValue(TW_INTERNAL_PATH, "/data/media/0");
293 UnMount(true);
294 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400295#endif
296#ifdef TW_INCLUDE_CRYPTO
297 Can_Be_Encrypted = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400298 char crypto_blkdev[255];
299 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
300 if (strcmp(crypto_blkdev, "error") != 0) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400301 DataManager::SetValue(TW_DATA_BLK_DEVICE, Primary_Block_Device);
Dees_Troy657c3092012-09-10 20:32:10 -0400302 DataManager::SetValue(TW_IS_DECRYPTED, 1);
303 Is_Encrypted = true;
304 Is_Decrypted = true;
305 Decrypted_Block_Device = crypto_blkdev;
Dees_Troy2673cec2013-04-02 20:22:16 +0000306 LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
Dees_Troy657c3092012-09-10 20:32:10 -0400307 } else if (!Mount(false)) {
Ethan Yonker71413f42014-02-26 13:36:08 -0600308 if (Is_Present) {
309#ifdef TW_INCLUDE_JB_CRYPTO
310 // No extra flags needed
311#else
312 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
313 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
314 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
315 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
316 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
317 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
318#ifdef CRYPTO_SD_FS_TYPE
319 property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
320 property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
321 property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
322#endif
323 property_set("rw.km_fips_status", "ready");
324#endif
325 if (cryptfs_check_footer() == 0) {
326 Is_Encrypted = true;
327 Is_Decrypted = false;
328 Can_Be_Mounted = false;
329 Current_File_System = "emmc";
330 Setup_Image(Display_Error);
331 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
332 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
333 DataManager::SetValue("tw_crypto_display", "");
334 } else {
335 LOGERR("Could not mount /data and unable to find crypto footer.\n");
336 }
337 } else {
338 LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
339 }
Gary Peck82599a82012-11-21 16:23:12 -0800340 } else {
341 // Filesystem is not encrypted and the mount
342 // succeeded, so get it back to the original
343 // unmounted state
344 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -0400345 }
Dees_Troy9b21af72012-10-01 15:51:46 -0400346 #ifdef RECOVERY_SDCARD_ON_DATA
347 if (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))
348 Recreate_Media_Folder();
349 #endif
350#else
351 #ifdef RECOVERY_SDCARD_ON_DATA
352 Recreate_Media_Folder();
353 #endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400354#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400355 } else if (Mount_Point == "/cache") {
356 Display_Name = "Cache";
Dees_Troya13d74f2013-03-24 08:54:55 -0500357 Backup_Display_Name = Display_Name;
358 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400359 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400360 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500361 Can_Be_Backed_Up = true;
Dees_Troyce2fe772012-09-28 12:34:33 -0400362 if (Mount(false) && !TWFunc::Path_Exists("/cache/recovery/.")) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000363 LOGINFO("Recreating /cache/recovery folder.\n");
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500364 if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500365 return -1;
Dees_Troyb46a6842012-09-25 11:06:46 -0400366 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400367 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400368 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400369 Display_Name = "DataData";
Dees_Troya13d74f2013-03-24 08:54:55 -0500370 Backup_Display_Name = Display_Name;
371 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400372 Is_SubPartition = true;
373 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400374 DataManager::SetValue(TW_HAS_DATADATA, 1);
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 = false; // This whole partition should be encrypted
Dees_Troy5bf43922012-09-07 16:07:55 -0400378 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400379 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400380 Display_Name = "SD-Ext";
Dees_Troya13d74f2013-03-24 08:54:55 -0500381 Backup_Display_Name = Display_Name;
382 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400383 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400384 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500385 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000386 Can_Encrypt_Backup = true;
387 Use_Userdata_Encryption = true;
Dees_Troy2c50e182012-09-26 20:05:28 -0400388 } else if (Mount_Point == "/boot") {
389 Display_Name = "Boot";
Dees_Troya13d74f2013-03-24 08:54:55 -0500390 Backup_Display_Name = Display_Name;
Dees_Troy2c50e182012-09-26 20:05:28 -0400391 DataManager::SetValue("tw_boot_is_mountable", 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500392 Can_Be_Backed_Up = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400393 }
394#ifdef TW_EXTERNAL_STORAGE_PATH
395 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
396 Is_Storage = true;
397 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
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#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000401 if (Mount_Point == "/sdcard" || Mount_Point == "/external_sd" || Mount_Point == "/external_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400402 Is_Storage = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400403 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500404 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400405#endif
Dees_Troyb05ddee2013-01-28 20:24:50 +0000406 }
Dees_Troy8170a922012-09-18 15:40:25 -0400407#ifdef TW_INTERNAL_STORAGE_PATH
408 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
409 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500410 Is_Settings_Storage = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400411 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troya13d74f2013-03-24 08:54:55 -0500412 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400413 }
414#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000415 if (Mount_Point == "/emmc" || Mount_Point == "/internal_sd" || Mount_Point == "/internal_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400416 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500417 Is_Settings_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500418 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400419 }
420#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400421 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400422 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400423 Setup_Image(Display_Error);
Dees_Troya13d74f2013-03-24 08:54:55 -0500424 if (Mount_Point == "/boot") {
425 Display_Name = "Boot";
426 Backup_Display_Name = Display_Name;
427 Can_Be_Backed_Up = true;
428 } else if (Mount_Point == "/recovery") {
429 Display_Name = "Recovery";
430 Backup_Display_Name = Display_Name;
Dees_Troya13d74f2013-03-24 08:54:55 -0500431 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400432 }
433
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400434 // Generate MTP ID
435 if (Is_Storage) {
436 (*initmtpid)++;
437 mtpid = *initmtpid;
438 }
439
Dees_Troy51127312012-09-08 13:08:49 -0400440 // Process any custom flags
441 if (Flags.size() > 0)
442 Process_Flags(Flags, Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400443 return true;
444}
445
Hashcode62bd9e02013-11-19 21:59:42 -0800446bool TWPartition::Process_FS_Flags(string& Options, int Flags) {
447 int i;
448 char *p;
449 char *savep;
450 char fs_options[250];
451
452 strlcpy(fs_options, Options.c_str(), sizeof(fs_options));
453 Options = "";
454
455 p = strtok_r(fs_options, ",", &savep);
456 while (p) {
457 /* Look for the flag "p" in the flag list "fl"
458 * If not found, the loop exits with fl[i].name being null.
459 */
460 for (i = 0; mount_flags[i].name; i++) {
461 if (strncmp(p, mount_flags[i].name, strlen(mount_flags[i].name)) == 0) {
462 Flags |= mount_flags[i].flag;
463 break;
464 }
465 }
466
467 if (!mount_flags[i].name) {
468 if (Options.size() > 0)
469 Options += ",";
470 Options += p;
471 }
472 p = strtok_r(NULL, ",", &savep);
473 }
474
475 return true;
476}
477
Dees_Troy51127312012-09-08 13:08:49 -0400478bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
479 char flags[MAX_FSTAB_LINE_LENGTH];
Dees_Troya13d74f2013-03-24 08:54:55 -0500480 int flags_len, index = 0, ptr_len;
Dees_Troy51127312012-09-08 13:08:49 -0400481 char* ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500482 bool skip = false, has_display_name = false, has_storage_name = false, has_backup_name = false;
Dees_Troy51127312012-09-08 13:08:49 -0400483
484 strcpy(flags, Flags.c_str());
485 flags_len = Flags.size();
486 for (index = 0; index < flags_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500487 if (flags[index] == 34)
488 skip = !skip;
489 if (!skip && flags[index] == ';')
Dees_Troy51127312012-09-08 13:08:49 -0400490 flags[index] = '\0';
491 }
492
493 index = 0;
494 while (index < flags_len) {
495 while (index < flags_len && flags[index] == '\0')
496 index++;
497 if (index >= flags_len)
498 continue;
499 ptr = flags + index;
Dees_Troya13d74f2013-03-24 08:54:55 -0500500 ptr_len = strlen(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400501 if (strcmp(ptr, "removable") == 0) {
502 Removable = true;
Ethan Yonker06c3f932014-02-02 22:11:14 -0600503 } else if (strncmp(ptr, "storage", 7) == 0) {
504 if (ptr_len == 7) {
Ethan Yonker06c3f932014-02-02 22:11:14 -0600505 Is_Storage = true;
506 } else if (ptr_len == 9) {
507 ptr += 9;
508 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
509 LOGINFO("storage set to true\n");
510 Is_Storage = true;
511 } else {
512 LOGINFO("storage set to false\n");
513 Is_Storage = false;
514 }
515 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500516 } else if (strcmp(ptr, "settingsstorage") == 0) {
517 Is_Storage = true;
Matt Mowerbf4efa32014-04-14 23:25:26 -0500518 } else if (strcmp(ptr, "andsec") == 0) {
519 Has_Android_Secure = true;
Dees_Troy63c8df72012-09-10 14:02:05 -0400520 } else if (strcmp(ptr, "canbewiped") == 0) {
521 Can_Be_Wiped = true;
Hashcodedabfd492013-08-29 22:45:30 -0700522 } else if (strcmp(ptr, "usermrf") == 0) {
523 Use_Rm_Rf = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500524 } else if (ptr_len > 7 && strncmp(ptr, "backup=", 7) == 0) {
525 ptr += 7;
526 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
527 Can_Be_Backed_Up = true;
528 else
529 Can_Be_Backed_Up = false;
Dees_Troy63c8df72012-09-10 14:02:05 -0400530 } else if (strcmp(ptr, "wipeingui") == 0) {
531 Can_Be_Wiped = true;
532 Wipe_Available_in_GUI = true;
533 } else if (strcmp(ptr, "wipeduringfactoryreset") == 0) {
534 Can_Be_Wiped = true;
535 Wipe_Available_in_GUI = true;
536 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500537 } else if (ptr_len > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) {
Dees_Troy2c4c26f2013-01-28 15:26:43 +0000538 ptr += 15;
Dees_Troy51127312012-09-08 13:08:49 -0400539 Is_SubPartition = true;
540 SubPartition_Of = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000541 } else if (strcmp(ptr, "ignoreblkid") == 0) {
542 Ignore_Blkid = true;
Dees_Troy16c2b312013-01-15 16:51:18 +0000543 } else if (strcmp(ptr, "retainlayoutversion") == 0) {
544 Retain_Layout_Version = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500545 } else if (ptr_len > 8 && strncmp(ptr, "symlink=", 8) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400546 ptr += 8;
547 Symlink_Path = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500548 } else if (ptr_len > 8 && strncmp(ptr, "display=", 8) == 0) {
549 has_display_name = true;
Dees_Troy51127312012-09-08 13:08:49 -0400550 ptr += 8;
Dees_Troya13d74f2013-03-24 08:54:55 -0500551 if (*ptr == '\"') ptr++;
Dees_Troy51127312012-09-08 13:08:49 -0400552 Display_Name = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500553 if (Display_Name.substr(Display_Name.size() - 1, 1) == "\"") {
554 Display_Name.resize(Display_Name.size() - 1);
555 }
556 } else if (ptr_len > 11 && strncmp(ptr, "storagename=", 11) == 0) {
557 has_storage_name = true;
558 ptr += 11;
559 if (*ptr == '\"') ptr++;
560 Storage_Name = ptr;
561 if (Storage_Name.substr(Storage_Name.size() - 1, 1) == "\"") {
562 Storage_Name.resize(Storage_Name.size() - 1);
563 }
564 } else if (ptr_len > 11 && strncmp(ptr, "backupname=", 10) == 0) {
565 has_backup_name = true;
566 ptr += 10;
567 if (*ptr == '\"') ptr++;
568 Backup_Display_Name = ptr;
569 if (Backup_Display_Name.substr(Backup_Display_Name.size() - 1, 1) == "\"") {
570 Backup_Display_Name.resize(Backup_Display_Name.size() - 1);
571 }
572 } else if (ptr_len > 10 && strncmp(ptr, "blocksize=", 10) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400573 ptr += 10;
574 Format_Block_Size = atoi(ptr);
Dees_Troya13d74f2013-03-24 08:54:55 -0500575 } else if (ptr_len > 7 && strncmp(ptr, "length=", 7) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400576 ptr += 7;
577 Length = atoi(ptr);
Dees_Troy83bd4832013-05-04 12:39:56 +0000578 } else if (ptr_len > 17 && strncmp(ptr, "canencryptbackup=", 17) == 0) {
579 ptr += 17;
580 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
581 Can_Encrypt_Backup = true;
582 else
583 Can_Encrypt_Backup = false;
584 } else if (ptr_len > 21 && strncmp(ptr, "userdataencryptbackup=", 21) == 0) {
585 ptr += 21;
586 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
587 Can_Encrypt_Backup = true;
588 Use_Userdata_Encryption = true;
589 } else {
590 Use_Userdata_Encryption = false;
591 }
Hashcode62bd9e02013-11-19 21:59:42 -0800592 } else if (ptr_len > 8 && strncmp(ptr, "fsflags=", 8) == 0) {
593 ptr += 8;
594 if (*ptr == '\"') ptr++;
595
596 Mount_Options = ptr;
597 if (Mount_Options.substr(Mount_Options.size() - 1, 1) == "\"") {
598 Mount_Options.resize(Mount_Options.size() - 1);
599 }
600 Process_FS_Flags(Mount_Options, Mount_Flags);
Dees_Troy51127312012-09-08 13:08:49 -0400601 } else {
602 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000603 LOGERR("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400604 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000605 LOGINFO("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400606 }
607 while (index < flags_len && flags[index] != '\0')
608 index++;
609 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500610 if (has_display_name && !has_storage_name)
611 Storage_Name = Display_Name;
612 if (!has_display_name && has_storage_name)
613 Display_Name = Storage_Name;
Dees_Troy74fb2e92013-04-15 14:35:47 +0000614 if (has_display_name && !has_backup_name && Backup_Display_Name != "Android Secure")
Dees_Troya13d74f2013-03-24 08:54:55 -0500615 Backup_Display_Name = Display_Name;
616 if (!has_display_name && has_backup_name)
617 Display_Name = Backup_Display_Name;
Dees_Troy51127312012-09-08 13:08:49 -0400618 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400619}
620
Dees_Troy5bf43922012-09-07 16:07:55 -0400621bool TWPartition::Is_File_System(string File_System) {
622 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400623 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400624 File_System == "ext4" ||
625 File_System == "vfat" ||
626 File_System == "ntfs" ||
627 File_System == "yaffs2" ||
bigbiff bigbiff3e146522012-11-14 14:32:59 -0500628 File_System == "exfat" ||
Dees_Troye5017042013-08-29 16:38:55 +0000629 File_System == "f2fs" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400630 File_System == "auto")
631 return true;
632 else
633 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400634}
635
Dees_Troy5bf43922012-09-07 16:07:55 -0400636bool TWPartition::Is_Image(string File_System) {
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400637 if (File_System == "emmc" || File_System == "mtd" || File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400638 return true;
639 else
640 return false;
641}
642
Dees_Troy51127312012-09-08 13:08:49 -0400643bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400644 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400645 if (mkdir(Path.c_str(), 0777) == -1) {
646 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000647 LOGERR("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400648 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000649 LOGINFO("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400650 return false;
651 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000652 LOGINFO("Created '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400653 return true;
654 }
655 }
656 return true;
657}
658
Dees_Troy5bf43922012-09-07 16:07:55 -0400659void TWPartition::Setup_File_System(bool Display_Error) {
660 struct statfs st;
661
662 Can_Be_Mounted = true;
663 Can_Be_Wiped = true;
664
Dees_Troy5bf43922012-09-07 16:07:55 -0400665 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400666 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400667 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
668 Backup_Name = Display_Name;
669 Backup_Method = FILES;
670}
671
672void TWPartition::Setup_Image(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400673 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
674 Backup_Name = Display_Name;
Gary Peck82599a82012-11-21 16:23:12 -0800675 if (Current_File_System == "emmc")
Dees_Troy5bf43922012-09-07 16:07:55 -0400676 Backup_Method = DD;
Gary Peck82599a82012-11-21 16:23:12 -0800677 else if (Current_File_System == "mtd" || Current_File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400678 Backup_Method = FLASH_UTILS;
679 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000680 LOGINFO("Unhandled file system '%s' on image '%s'\n", Current_File_System.c_str(), Display_Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400681 if (Find_Partition_Size()) {
682 Used = Size;
683 Backup_Size = Size;
Dees_Troy51a0e822012-09-05 15:24:24 -0400684 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400685 if (Display_Error)
Dees Troyd932ce12013-10-18 17:12:59 +0000686 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400687 else
Dees Troyd932ce12013-10-18 17:12:59 +0000688 LOGINFO("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400689 }
690}
691
Dees_Troye58d5262012-09-21 12:27:57 -0400692void TWPartition::Setup_AndSec(void) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500693 Backup_Display_Name = "Android Secure";
Dees_Troye58d5262012-09-21 12:27:57 -0400694 Backup_Name = "and-sec";
Dees_Troya13d74f2013-03-24 08:54:55 -0500695 Can_Be_Backed_Up = true;
Dees_Troye58d5262012-09-21 12:27:57 -0400696 Has_Android_Secure = true;
697 Symlink_Path = Mount_Point + "/.android_secure";
698 Symlink_Mount_Point = "/and-sec";
699 Backup_Path = Symlink_Mount_Point;
700 Make_Dir("/and-sec", true);
701 Recreate_AndSec_Folder();
Ethan Yonkerd4d10732014-02-03 15:27:52 -0600702 Mount_Storage_Retry();
Dees_Troye58d5262012-09-21 12:27:57 -0400703}
704
Dees_Troy5bf43922012-09-07 16:07:55 -0400705void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
706 char device[512], realDevice[512];
707
708 strcpy(device, Block.c_str());
709 memset(realDevice, 0, sizeof(realDevice));
710 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
711 {
712 strcpy(device, realDevice);
713 memset(realDevice, 0, sizeof(realDevice));
714 }
715
716 if (device[0] != '/') {
717 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000718 LOGERR("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400719 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000720 LOGINFO("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400721 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400722 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400723 Block = device;
724 return;
725 }
726}
727
Dees_Troy8e337f32012-10-13 22:07:49 -0400728void TWPartition::Mount_Storage_Retry(void) {
729 // On some devices, storage doesn't want to mount right away, retry and sleep
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500730 if (!Mount(true)) {
Dees_Troy8e337f32012-10-13 22:07:49 -0400731 int retry_count = 5;
732 while (retry_count > 0 && !Mount(false)) {
733 usleep(500000);
734 retry_count--;
735 }
736 Mount(true);
737 }
738}
739
Dees_Troy38bd7602012-09-14 13:33:53 -0400740bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
741 FILE *fp = NULL;
742 char line[255];
743
744 fp = fopen("/proc/mtd", "rt");
745 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000746 LOGERR("Device does not support /proc/mtd\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400747 return false;
748 }
749
750 while (fgets(line, sizeof(line), fp) != NULL)
751 {
752 char device[32], label[32];
753 unsigned long size = 0;
754 char* fstype = NULL;
755 int deviceId;
756
757 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
758
759 // Skip header and blank lines
760 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
761 continue;
762
763 // Strip off the trailing " from the label
764 label[strlen(label)-1] = '\0';
765
766 if (strcmp(label, MTD_Name.c_str()) == 0) {
767 // We found our device
768 // Strip off the trailing : from the device
769 device[strlen(device)-1] = '\0';
770 if (sscanf(device,"mtd%d", &deviceId) == 1) {
771 sprintf(device, "/dev/block/mtdblock%d", deviceId);
772 Primary_Block_Device = device;
Dees_Troy76543db2013-06-19 16:24:30 +0000773 fclose(fp);
774 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400775 }
776 }
777 }
778 fclose(fp);
779
780 return false;
781}
782
Dees_Troy51127312012-09-08 13:08:49 -0400783bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
784 struct statfs st;
785 string Local_Path = Mount_Point + "/.";
786
787 if (!Mount(Display_Error))
788 return false;
789
790 if (statfs(Local_Path.c_str(), &st) != 0) {
791 if (!Removable) {
792 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000793 LOGERR("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400794 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000795 LOGINFO("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400796 }
797 return false;
798 }
799 Size = (st.f_blocks * st.f_bsize);
800 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
801 Free = (st.f_bfree * st.f_bsize);
802 Backup_Size = Used;
803 return true;
804}
805
806bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400807 FILE* fp;
808 char command[255], line[512];
809 int include_block = 1;
810 unsigned int min_len;
811
812 if (!Mount(Display_Error))
813 return false;
814
Dees_Troy38bd7602012-09-14 13:33:53 -0400815 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -0400816 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +0200817 TWFunc::Exec_Cmd(command);
Dees_Troy51127312012-09-08 13:08:49 -0400818 fp = fopen("/tmp/dfoutput.txt", "rt");
819 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000820 LOGINFO("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400821 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400822 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400823
824 while (fgets(line, sizeof(line), fp) != NULL)
825 {
826 unsigned long blocks, used, available;
827 char device[64];
828 char tmpString[64];
829
830 if (strncmp(line, "Filesystem", 10) == 0)
831 continue;
832 if (strlen(line) < min_len) {
833 include_block = 0;
834 continue;
835 }
836 if (include_block) {
837 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
838 } else {
839 // The device block string is so long that the df information is on the next line
840 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -0400841 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400842 while (tmpString[space_count] == 32)
843 space_count++;
844 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
845 }
846
847 // Adjust block size to byte size
848 Size = blocks * 1024ULL;
849 Used = used * 1024ULL;
850 Free = available * 1024ULL;
851 Backup_Size = Used;
852 }
853 fclose(fp);
854 return true;
855}
856
Dees_Troy5bf43922012-09-07 16:07:55 -0400857bool TWPartition::Find_Partition_Size(void) {
858 FILE* fp;
859 char line[512];
860 string tmpdevice;
861
igoriok87e3d932013-01-31 21:03:53 +0200862 fp = fopen("/proc/dumchar_info", "rt");
863 if (fp != NULL) {
864 while (fgets(line, sizeof(line), fp) != NULL)
865 {
866 char label[32], device[32];
867 unsigned long size = 0;
868
869 sscanf(line, "%s %lx %*lx %*lu %s", label, &size, device);
870
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500871 // Skip header, annotation and blank lines
igoriok87e3d932013-01-31 21:03:53 +0200872 if ((strncmp(device, "/dev/", 5) != 0) || (strlen(line) < 8))
873 continue;
874
875 tmpdevice = "/dev/";
876 tmpdevice += label;
877 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
878 Size = size;
879 fclose(fp);
880 return true;
881 }
882 }
883 }
884
Dees_Troy5bf43922012-09-07 16:07:55 -0400885 // In this case, we'll first get the partitions we care about (with labels)
886 fp = fopen("/proc/partitions", "rt");
887 if (fp == NULL)
888 return false;
889
890 while (fgets(line, sizeof(line), fp) != NULL)
891 {
892 unsigned long major, minor, blocks;
893 char device[512];
894 char tmpString[64];
895
Dees_Troy63c8df72012-09-10 14:02:05 -0400896 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400897 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
898
899 tmpdevice = "/dev/block/";
900 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -0400901 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400902 // Adjust block size to byte size
903 Size = blocks * 1024ULL;
904 fclose(fp);
905 return true;
906 }
907 }
908 fclose(fp);
909 return false;
910}
911
Dees_Troy5bf43922012-09-07 16:07:55 -0400912bool TWPartition::Is_Mounted(void) {
913 if (!Can_Be_Mounted)
914 return false;
915
916 struct stat st1, st2;
917 string test_path;
918
919 // Check to see if the mount point directory exists
920 test_path = Mount_Point + "/.";
921 if (stat(test_path.c_str(), &st1) != 0) return false;
922
923 // Check to see if the directory above the mount point exists
924 test_path = Mount_Point + "/../.";
925 if (stat(test_path.c_str(), &st2) != 0) return false;
926
927 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
928 int ret = (st1.st_dev != st2.st_dev) ? true : false;
929
930 return ret;
931}
932
933bool TWPartition::Mount(bool Display_Error) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000934 int exfat_mounted = 0;
935
Dees_Troy5bf43922012-09-07 16:07:55 -0400936 if (Is_Mounted()) {
937 return true;
938 } else if (!Can_Be_Mounted) {
939 return false;
940 }
Dees_Troy38bd7602012-09-14 13:33:53 -0400941
942 Find_Actual_Block_Device();
943
944 // Check the current file system before mounting
945 Check_FS_Type();
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000946 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/exfat-fuse")) {
Dees_Troye34c1332013-02-06 19:13:00 +0000947 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 +0000948 LOGINFO("cmd: %s\n", cmd.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000949 string result;
950 if (TWFunc::Exec_Cmd(cmd, result) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000951 LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000952 Current_File_System = "vfat";
953 } else {
954#ifdef TW_NO_EXFAT_FUSE
955 UnMount(false);
956 // We'll let the kernel handle it but using exfat-fuse to detect if the file system is actually exfat
957 // Some kernels let us mount vfat as exfat which doesn't work out too well
958#else
959 exfat_mounted = 1;
960#endif
961 }
962 }
Dees_Troy22042032012-12-18 21:23:08 +0000963 if (Fstab_File_System == "yaffs2") {
964 // mount an MTD partition as a YAFFS2 filesystem.
Dees_Troy76543db2013-06-19 16:24:30 +0000965 const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
966 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
967 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
968 if (Display_Error)
969 LOGERR("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
970 else
971 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
972 return false;
973 } else {
974 LOGINFO("Mounted '%s' (MTD) as RO\n", Mount_Point.c_str());
975 return true;
976 }
977 } else {
978 struct stat st;
979 string test_path = Mount_Point;
980 if (stat(test_path.c_str(), &st) < 0) {
981 if (Display_Error)
982 LOGERR("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
983 else
984 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
985 return false;
986 }
987 mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
988 if (new_mode != st.st_mode) {
989 LOGINFO("Fixing execute permissions for %s\n", Mount_Point.c_str());
990 if (chmod(Mount_Point.c_str(), new_mode) < 0) {
991 if (Display_Error)
992 LOGERR("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
993 else
994 LOGINFO("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
995 return false;
996 }
997 }
Dees_Troy22042032012-12-18 21:23:08 +0000998 return true;
Dees_Troy76543db2013-06-19 16:24:30 +0000999 }
Dees Troy216e0422014-02-07 03:46:42 +00001000 } else if (!exfat_mounted && mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), Mount_Flags, Mount_Options.c_str()) != 0 && mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), Mount_Flags, NULL) != 0) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001001#ifdef TW_NO_EXFAT_FUSE
1002 if (Current_File_System == "exfat") {
Dees_Troy2673cec2013-04-02 20:22:16 +00001003 LOGINFO("Mounting exfat failed, trying vfat...\n");
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001004 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), "vfat", 0, NULL) != 0) {
Dees_Troy85f44ed2013-01-09 18:42:36 +00001005 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001006 LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
Dees_Troy85f44ed2013-01-09 18:42:36 +00001007 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001008 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
Hashcode62bd9e02013-11-19 21:59:42 -08001009 LOGINFO("Actual block device: '%s', current file system: '%s', flags: 0x%8x, options: '%s'\n", Actual_Block_Device.c_str(), Current_File_System.c_str(), Mount_Flags, Mount_Options.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001010 return false;
Dees_Troy85f44ed2013-01-09 18:42:36 +00001011 }
Dees_Troyb05ddee2013-01-28 20:24:50 +00001012 } else {
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001013#endif
bigbiff bigbiff26774a02014-03-29 18:22:00 -04001014 if (!Removable && Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001015 LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001016 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001017 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
1018 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 +00001019 return false;
1020#ifdef TW_NO_EXFAT_FUSE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001021 }
1022#endif
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001023 }
1024#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1025 string MetaEcfsFile = EXPAND(TW_EXTERNAL_STORAGE_PATH);
1026 MetaEcfsFile += "/.MetaEcfsFile";
1027 if (EcryptFS_Password.size() > 0 && PartitionManager.Mount_By_Path("/data", false) && TWFunc::Path_Exists(MetaEcfsFile)) {
1028 if (mount_ecryptfs_drive(EcryptFS_Password.c_str(), Mount_Point.c_str(), Mount_Point.c_str(), 0) != 0) {
1029 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001030 LOGERR("Unable to mount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001031 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001032 LOGINFO("Unable to mount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001033 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001034 LOGINFO("Successfully mounted ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001035 Is_Decrypted = true;
Dees_Troy51127312012-09-08 13:08:49 -04001036 }
Dees_Troy066eb302013-08-23 17:20:32 +00001037 } else if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
1038 if (Is_Decrypted)
1039 LOGINFO("Mounting external storage, '%s' is not encrypted\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001040 Is_Decrypted = false;
1041 }
1042#endif
1043 if (Removable)
1044 Update_Size(Display_Error);
1045
1046 if (!Symlink_Mount_Point.empty()) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001047 string Command = "mount '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
1048 TWFunc::Exec_Cmd(Command);
Dees_Troy5bf43922012-09-07 16:07:55 -04001049 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001050 return true;
1051}
1052
1053bool TWPartition::UnMount(bool Display_Error) {
1054 if (Is_Mounted()) {
1055 int never_unmount_system;
1056
1057 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
1058 if (never_unmount_system == 1 && Mount_Point == "/system")
1059 return true; // Never unmount system if you're not supposed to unmount it
1060
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001061 if (Is_Storage)
1062 TWFunc::Toggle_MTP(false);
1063
Dees_Troyc8bafa12013-01-10 15:43:00 +00001064#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1065 if (EcryptFS_Password.size() > 0) {
1066 if (unmount_ecryptfs_drive(Mount_Point.c_str()) != 0) {
1067 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001068 LOGERR("Unable to unmount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001069 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001070 LOGINFO("Unable to unmount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001071 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001072 LOGINFO("Successfully unmounted ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001073 }
1074 }
1075#endif
1076
Dees_Troy38bd7602012-09-14 13:33:53 -04001077 if (!Symlink_Mount_Point.empty())
1078 umount(Symlink_Mount_Point.c_str());
1079
Dees_Troyb05ddee2013-01-28 20:24:50 +00001080 umount(Mount_Point.c_str());
1081 if (Is_Mounted()) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001082 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001083 LOGERR("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001084 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001085 LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001086 return false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001087 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -04001088 return true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001089 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001090 } else {
1091 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001092 }
1093}
1094
Gary Peck43acadf2012-11-21 21:19:01 -08001095bool TWPartition::Wipe(string New_File_System) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001096 bool wiped = false, update_crypt = false, recreate_media = true, mtp_toggle = true;
Dees_Troy16c2b312013-01-15 16:51:18 +00001097 int check;
1098 string Layout_Filename = Mount_Point + "/.layout_version";
1099
Dees_Troy38bd7602012-09-14 13:33:53 -04001100 if (!Can_Be_Wiped) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001101 LOGERR("Partition '%s' cannot be wiped.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001102 return false;
1103 }
1104
Dees_Troyc51f1f92012-09-20 15:32:13 -04001105 if (Mount_Point == "/cache")
Dees_Troy2673cec2013-04-02 20:22:16 +00001106 Log_Offset = 0;
Dees_Troyc51f1f92012-09-20 15:32:13 -04001107
Dees_Troyce675462013-01-09 19:48:21 +00001108#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1109 if (Mount_Point == "/data" && Mount(false)) {
1110 if (TWFunc::Path_Exists("/data/system/edk_p_sd"))
1111 TWFunc::copy_file("/data/system/edk_p_sd", "/tmp/edk_p_sd", 0600);
1112 }
1113#endif
1114
Dees_Troy16c2b312013-01-15 16:51:18 +00001115 if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
1116 TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
1117 else
1118 unlink("/.layout_version");
Dees_Troy38bd7602012-09-14 13:33:53 -04001119
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001120 if (Has_Data_Media && Current_File_System == New_File_System) {
Dees_Troy16c2b312013-01-15 16:51:18 +00001121 wiped = Wipe_Data_Without_Wiping_Media();
Ethan Yonker5eac2222014-06-11 12:22:55 -05001122 recreate_media = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001123 mtp_toggle = false;
Dees_Troy16c2b312013-01-15 16:51:18 +00001124 } else {
Dees_Troy16c2b312013-01-15 16:51:18 +00001125 DataManager::GetValue(TW_RM_RF_VAR, check);
1126
Hashcodedabfd492013-08-29 22:45:30 -07001127 if (check || Use_Rm_Rf)
Dees_Troy16c2b312013-01-15 16:51:18 +00001128 wiped = Wipe_RMRF();
1129 else if (New_File_System == "ext4")
1130 wiped = Wipe_EXT4();
1131 else if (New_File_System == "ext2" || New_File_System == "ext3")
1132 wiped = Wipe_EXT23(New_File_System);
1133 else if (New_File_System == "vfat")
1134 wiped = Wipe_FAT();
1135 else if (New_File_System == "exfat")
1136 wiped = Wipe_EXFAT();
1137 else if (New_File_System == "yaffs2")
1138 wiped = Wipe_MTD();
Dees_Troye5017042013-08-29 16:38:55 +00001139 else if (New_File_System == "f2fs")
1140 wiped = Wipe_F2FS();
Dees_Troy16c2b312013-01-15 16:51:18 +00001141 else {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001142 if (Is_Storage) {
1143 TWFunc::Toggle_MTP(true);
1144 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001145 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 +00001146 unlink("/.layout_version");
1147 return false;
1148 }
1149 update_crypt = wiped;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001150 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001151
Gary Pecke8bc5d72012-12-21 06:45:25 -08001152 if (wiped) {
Dees_Troyce675462013-01-09 19:48:21 +00001153#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1154 if (Mount_Point == "/data" && Mount(false)) {
1155 if (TWFunc::Path_Exists("/tmp/edk_p_sd")) {
1156 Make_Dir("/data/system", true);
1157 TWFunc::copy_file("/tmp/edk_p_sd", "/data/system/edk_p_sd", 0600);
1158 }
1159 }
1160#endif
Dees_Troy16c2b312013-01-15 16:51:18 +00001161
Dees_Troy1c1ac442013-01-17 21:42:14 +00001162 if (Mount_Point == "/cache")
1163 DataManager::Output_Version();
1164
Dees_Troy16c2b312013-01-15 16:51:18 +00001165 if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
1166 TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
1167
1168 if (update_crypt) {
1169 Setup_File_System(false);
1170 if (Is_Encrypted && !Is_Decrypted) {
1171 // just wiped an encrypted partition back to its unencrypted state
1172 Is_Encrypted = false;
1173 Is_Decrypted = false;
1174 Decrypted_Block_Device = "";
1175 if (Mount_Point == "/data") {
1176 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1177 DataManager::SetValue(TW_IS_DECRYPTED, 0);
1178 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001179 }
1180 }
Ethan Yonker5eac2222014-06-11 12:22:55 -05001181
1182 if (Mount_Point == "/data" && Has_Data_Media && recreate_media) {
1183 Recreate_Media_Folder();
1184 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001185 }
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001186 if (Is_Storage && mtp_toggle) {
1187 TWFunc::Toggle_MTP(true);
1188 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001189 return wiped;
Dees_Troy51a0e822012-09-05 15:24:24 -04001190}
1191
Gary Peck43acadf2012-11-21 21:19:01 -08001192bool TWPartition::Wipe() {
Gary Peck82599a82012-11-21 16:23:12 -08001193 if (Is_File_System(Current_File_System))
1194 return Wipe(Current_File_System);
1195 else
1196 return Wipe(Fstab_File_System);
Gary Peck43acadf2012-11-21 21:19:01 -08001197}
1198
Dees_Troye58d5262012-09-21 12:27:57 -04001199bool TWPartition::Wipe_AndSec(void) {
1200 if (!Has_Android_Secure)
1201 return false;
1202
Dees_Troye58d5262012-09-21 12:27:57 -04001203 if (!Mount(true))
1204 return false;
1205
Dees_Troy2673cec2013-04-02 20:22:16 +00001206 gui_print("Wiping %s\n", Backup_Display_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001207 TWFunc::removeDir(Mount_Point + "/.android_secure/", true);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001208 return true;
Dees_Troye58d5262012-09-21 12:27:57 -04001209}
1210
Ethan Yonker87c7bac2014-05-25 21:41:08 -05001211bool TWPartition::Can_Repair() {
1212 if (Current_File_System == "vfat" && TWFunc::Path_Exists("/sbin/dosfsck"))
1213 return true;
1214 else if ((Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") && TWFunc::Path_Exists("/sbin/e2fsck"))
1215 return true;
1216 else if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/fsck.exfat"))
1217 return true;
1218 else if (Current_File_System == "f2fs" && TWFunc::Path_Exists("/sbin/fsck.f2fs"))
1219 return true;
1220 return false;
1221}
1222
1223bool TWPartition::Repair() {
1224 string command;
1225
1226 if (Current_File_System == "vfat") {
1227 if (!TWFunc::Path_Exists("/sbin/dosfsck")) {
1228 gui_print("dosfsck does not exist! Cannot repair!\n");
1229 return false;
1230 }
1231 if (!UnMount(true))
1232 return false;
1233 gui_print("Repairing %s using dosfsck...\n", Display_Name.c_str());
1234 Find_Actual_Block_Device();
1235 command = "/sbin/dosfsck -y " + Actual_Block_Device;
1236 LOGINFO("Repair command: %s\n", command.c_str());
1237 if (TWFunc::Exec_Cmd(command) == 0) {
1238 gui_print("Done.\n");
1239 return true;
1240 } else {
1241 LOGERR("Unable to repair '%s'.\n", Mount_Point.c_str());
1242 return false;
1243 }
1244 }
1245 if (Current_File_System == "ext2" || Current_File_System == "ext3" || Current_File_System == "ext4") {
1246 if (!TWFunc::Path_Exists("/sbin/e2fsck")) {
1247 gui_print("e2fsck does not exist! Cannot repair!\n");
1248 return false;
1249 }
1250 if (!UnMount(true))
1251 return false;
1252 gui_print("Repairing %s using e2fsck...\n", Display_Name.c_str());
1253 Find_Actual_Block_Device();
1254 command = "/sbin/e2fsck -p " + Actual_Block_Device;
1255 LOGINFO("Repair command: %s\n", command.c_str());
1256 if (TWFunc::Exec_Cmd(command) == 0) {
1257 gui_print("Done.\n");
1258 return true;
1259 } else {
1260 LOGERR("Unable to repair '%s'.\n", Mount_Point.c_str());
1261 return false;
1262 }
1263 }
1264 if (Current_File_System == "exfat") {
1265 if (!TWFunc::Path_Exists("/sbin/fsck.exfat")) {
1266 gui_print("fsck.exfat does not exist! Cannot repair!\n");
1267 return false;
1268 }
1269 if (!UnMount(true))
1270 return false;
1271 gui_print("Repairing %s using fsck.exfat...\n", Display_Name.c_str());
1272 Find_Actual_Block_Device();
1273 command = "/sbin/fsck.exfat " + Actual_Block_Device;
1274 LOGINFO("Repair command: %s\n", command.c_str());
1275 if (TWFunc::Exec_Cmd(command) == 0) {
1276 gui_print("Done.\n");
1277 return true;
1278 } else {
1279 LOGERR("Unable to repair '%s'.\n", Mount_Point.c_str());
1280 return false;
1281 }
1282 }
1283 if (Current_File_System == "f2fs") {
1284 if (!TWFunc::Path_Exists("/sbin/fsck.f2fs")) {
1285 gui_print("fsck.f2fs does not exist! Cannot repair!\n");
1286 return false;
1287 }
1288 if (!UnMount(true))
1289 return false;
1290 gui_print("Repairing %s using fsck.f2fs...\n", Display_Name.c_str());
1291 Find_Actual_Block_Device();
1292 command = "/sbin/fsck.f2fs " + Actual_Block_Device;
1293 LOGINFO("Repair command: %s\n", command.c_str());
1294 if (TWFunc::Exec_Cmd(command) == 0) {
1295 gui_print("Done.\n");
1296 return true;
1297 } else {
1298 LOGERR("Unable to repair '%s'.\n", Mount_Point.c_str());
1299 return false;
1300 }
1301 }
1302 return false;
1303}
1304
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001305bool TWPartition::Backup(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001306 if (Backup_Method == FILES)
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001307 return Backup_Tar(backup_folder, overall_size, other_backups_size);
Dees_Troy38bd7602012-09-14 13:33:53 -04001308 else if (Backup_Method == DD)
1309 return Backup_DD(backup_folder);
1310 else if (Backup_Method == FLASH_UTILS)
1311 return Backup_Dump_Image(backup_folder);
Dees_Troy2673cec2013-04-02 20:22:16 +00001312 LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001313 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001314}
1315
Dees_Troy43d8b002012-09-17 16:00:01 -04001316bool TWPartition::Check_MD5(string restore_folder) {
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001317 string Full_Filename, md5file;
Dees_Troy43d8b002012-09-17 16:00:01 -04001318 char split_filename[512];
1319 int index = 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001320 twrpDigest md5sum;
Dees_Troy43d8b002012-09-17 16:00:01 -04001321
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001322 memset(split_filename, 0, sizeof(split_filename));
Dees_Troy43d8b002012-09-17 16:00:01 -04001323 Full_Filename = restore_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04001324 if (!TWFunc::Path_Exists(Full_Filename)) {
1325 // This is a split archive, we presume
1326 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
Dees_Troy2673cec2013-04-02 20:22:16 +00001327 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001328 md5file = split_filename;
1329 md5file += ".md5";
1330 if (!TWFunc::Path_Exists(md5file)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001331 LOGERR("No md5 file found for '%s'.\n", split_filename);
1332 LOGERR("Please unselect Enable MD5 verification to restore.\n");
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001333 return false;
1334 }
1335 md5sum.setfn(split_filename);
Dees_Troy83bd4832013-05-04 12:39:56 +00001336 while (index < 1000) {
1337 if (TWFunc::Path_Exists(split_filename) && md5sum.verify_md5digest() != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001338 LOGERR("MD5 failed to match on '%s'.\n", split_filename);
Dees_Troy43d8b002012-09-17 16:00:01 -04001339 return false;
1340 }
1341 index++;
1342 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001343 md5sum.setfn(split_filename);
Dees_Troy43d8b002012-09-17 16:00:01 -04001344 }
Dees_Troy4a2a1262012-09-18 09:33:47 -04001345 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -04001346 } else {
1347 // Single file archive
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001348 md5file = Full_Filename + ".md5";
1349 if (!TWFunc::Path_Exists(md5file)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001350 LOGERR("No md5 file found for '%s'.\n", Full_Filename.c_str());
1351 LOGERR("Please unselect Enable MD5 verification to restore.\n");
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001352 return false;
1353 }
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001354 md5sum.setfn(Full_Filename);
1355 if (md5sum.verify_md5digest() != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001356 LOGERR("MD5 failed to match on '%s'.\n", Full_Filename.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001357 return false;
1358 } else
1359 return true;
1360 }
1361 return false;
1362}
1363
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001364bool TWPartition::Restore(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) {
Gary Peck43acadf2012-11-21 21:19:01 -08001365 string Restore_File_System;
1366
1367 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy2673cec2013-04-02 20:22:16 +00001368 LOGINFO("Restore filename is: %s\n", Backup_FileName.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001369
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001370 Restore_File_System = Get_Restore_File_System(restore_folder);
1371
1372 if (Is_File_System(Restore_File_System))
1373 return Restore_Tar(restore_folder, Restore_File_System, total_restore_size, already_restored_size);
1374 else if (Is_Image(Restore_File_System)) {
1375 *already_restored_size += TWFunc::Get_File_Size(Backup_Name);
1376 if (Restore_File_System == "emmc")
1377 return Restore_DD(restore_folder, total_restore_size, already_restored_size);
1378 else if (Restore_File_System == "mtd" || Restore_File_System == "bml")
1379 return Restore_Flash_Image(restore_folder, total_restore_size, already_restored_size);
1380 }
1381
1382 LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str());
1383 return false;
1384}
1385
1386string TWPartition::Get_Restore_File_System(string restore_folder) {
1387 size_t first_period, second_period;
1388 string Restore_File_System;
1389
Gary Peck43acadf2012-11-21 21:19:01 -08001390 // Parse backup filename to extract the file system before wiping
1391 first_period = Backup_FileName.find(".");
1392 if (first_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001393 LOGERR("Unable to find file system (first period).\n");
Gary Peck43acadf2012-11-21 21:19:01 -08001394 return false;
1395 }
1396 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
1397 second_period = Restore_File_System.find(".");
1398 if (second_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001399 LOGERR("Unable to find file system (second period).\n");
Gary Peck43acadf2012-11-21 21:19:01 -08001400 return false;
1401 }
1402 Restore_File_System.resize(second_period);
Dees_Troy2673cec2013-04-02 20:22:16 +00001403 LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001404 return Restore_File_System;
Dees_Troy51a0e822012-09-05 15:24:24 -04001405}
1406
1407string TWPartition::Backup_Method_By_Name() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001408 if (Backup_Method == NONE)
1409 return "none";
1410 else if (Backup_Method == FILES)
1411 return "files";
1412 else if (Backup_Method == DD)
1413 return "dd";
1414 else if (Backup_Method == FLASH_UTILS)
1415 return "flash_utils";
1416 else
1417 return "undefined";
1418 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -04001419}
1420
1421bool TWPartition::Decrypt(string Password) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001422 LOGINFO("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001423 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -04001424 return 1;
1425}
1426
1427bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001428 bool Save_Data_Media = Has_Data_Media;
1429
1430 if (!UnMount(true))
1431 return false;
1432
Dees_Troy38bd7602012-09-14 13:33:53 -04001433 Has_Data_Media = false;
Dees_Troy74fb2e92013-04-15 14:35:47 +00001434 Decrypted_Block_Device = "";
1435 Is_Decrypted = false;
1436 Is_Encrypted = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001437 Find_Actual_Block_Device();
1438 bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
Gary Pecke8bc5d72012-12-21 06:45:25 -08001439 if (Wipe(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001440 Has_Data_Media = Save_Data_Media;
1441 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
1442 Recreate_Media_Folder();
1443 }
Ethan Yonker83e82572014-04-04 10:59:28 -05001444#ifndef TW_OEM_BUILD
Dees_Troy2673cec2013-04-02 20:22:16 +00001445 gui_print("You may need to reboot recovery to be able to use /data again.\n");
Ethan Yonker83e82572014-04-04 10:59:28 -05001446#endif
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001447 TWFunc::Toggle_MTP(mtp_was_enabled);
Dees_Troy38bd7602012-09-14 13:33:53 -04001448 return true;
1449 } else {
1450 Has_Data_Media = Save_Data_Media;
Dees_Troy2673cec2013-04-02 20:22:16 +00001451 LOGERR("Unable to format to remove encryption.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001452 return false;
1453 }
1454 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001455}
1456
1457void TWPartition::Check_FS_Type() {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001458 const char* type;
1459 blkid_probe pr;
Dees_Troy5bf43922012-09-07 16:07:55 -04001460
Dees_Troy68cab492012-12-12 19:29:35 +00001461 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd" || Fstab_File_System == "bml" || Ignore_Blkid)
1462 return; // Running blkid on some mtd devices causes a massive crash or needs to be skipped
Dees_Troy5bf43922012-09-07 16:07:55 -04001463
Dees_Troy38bd7602012-09-14 13:33:53 -04001464 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -04001465 if (!Is_Present)
1466 return;
Dees_Troy51127312012-09-08 13:08:49 -04001467
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001468 pr = blkid_new_probe_from_filename(Actual_Block_Device.c_str());
1469 if (blkid_do_fullprobe(pr)) {
1470 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001471 LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001472 return;
Dees_Troy5bf43922012-09-07 16:07:55 -04001473 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001474
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001475 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001476 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001477 LOGINFO("can't find filesystem on device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001478 return;
1479 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001480
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001481 Current_File_System = type;
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001482 blkid_free_probe(pr);
Dees_Troy51a0e822012-09-05 15:24:24 -04001483}
1484
Gary Peck43acadf2012-11-21 21:19:01 -08001485bool TWPartition::Wipe_EXT23(string File_System) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001486 if (!UnMount(true))
1487 return false;
1488
Dees_Troy43d8b002012-09-17 16:00:01 -04001489 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001490 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001491
Dees_Troy2673cec2013-04-02 20:22:16 +00001492 gui_print("Formatting %s using mke2fs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001493 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001494 command = "mke2fs -t " + File_System + " -m 0 " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001495 LOGINFO("mke2fs command: %s\n", command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001496 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001497 Current_File_System = File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04001498 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001499 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001500 return true;
1501 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001502 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001503 return false;
1504 }
1505 } else
1506 return Wipe_RMRF();
1507
1508 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001509}
1510
1511bool TWPartition::Wipe_EXT4() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001512 if (!UnMount(true))
1513 return false;
1514
Dees_Troyb3265ab2013-08-30 02:59:14 +00001515#if defined(HAVE_SELINUX) && defined(USE_EXT4)
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001516 int ret;
1517 char *secontext = NULL;
1518
Dees_Troya95f55c2013-08-17 13:14:43 +00001519 gui_print("Formatting %s using make_ext4fs function.\n", Display_Name.c_str());
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001520
Dees Troy99c8dbf2014-03-10 16:53:58 +00001521 if (!selinux_handle || selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001522 LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
1523 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
1524 } else {
1525 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
1526 }
1527 if (ret != 0) {
Dees_Troya95f55c2013-08-17 13:14:43 +00001528 LOGERR("Unable to wipe '%s' using function call.\n", Mount_Point.c_str());
1529 return false;
1530 } else {
bigbiff bigbiffc49d7062013-10-11 20:28:00 -04001531 string sedir = Mount_Point + "/lost+found";
1532 PartitionManager.Mount_By_Path(sedir.c_str(), true);
1533 rmdir(sedir.c_str());
1534 mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
Dees_Troya95f55c2013-08-17 13:14:43 +00001535 return true;
1536 }
1537#else
Dees_Troy43d8b002012-09-17 16:00:01 -04001538 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001539 string Command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001540
Dees_Troy2673cec2013-04-02 20:22:16 +00001541 gui_print("Formatting %s using make_ext4fs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001542 Find_Actual_Block_Device();
1543 Command = "make_ext4fs";
1544 if (!Is_Decrypted && Length != 0) {
1545 // Only use length if we're not decrypted
1546 char len[32];
1547 sprintf(len, "%i", Length);
1548 Command += " -l ";
1549 Command += len;
1550 }
Dees_Troy5295d582013-09-06 15:51:08 +00001551 if (TWFunc::Path_Exists("/file_contexts")) {
1552 Command += " -S /file_contexts";
1553 }
1554 Command += " -a " + Mount_Point + " " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001555 LOGINFO("make_ext4fs command: %s\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001556 if (TWFunc::Exec_Cmd(Command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001557 Current_File_System = "ext4";
Dees_Troye58d5262012-09-21 12:27:57 -04001558 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001559 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001560 return true;
1561 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001562 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001563 return false;
1564 }
1565 } else
Gary Peck43acadf2012-11-21 21:19:01 -08001566 return Wipe_EXT23("ext4");
Dees_Troya95f55c2013-08-17 13:14:43 +00001567#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001568 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001569}
1570
1571bool TWPartition::Wipe_FAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001572 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001573
Dees_Troy43d8b002012-09-17 16:00:01 -04001574 if (TWFunc::Path_Exists("/sbin/mkdosfs")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001575 if (!UnMount(true))
1576 return false;
1577
Dees_Troy2673cec2013-04-02 20:22:16 +00001578 gui_print("Formatting %s using mkdosfs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001579 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001580 command = "mkdosfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001581 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001582 Current_File_System = "vfat";
Dees_Troye58d5262012-09-21 12:27:57 -04001583 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001584 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001585 return true;
1586 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001587 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001588 return false;
1589 }
1590 return true;
1591 }
1592 else
1593 return Wipe_RMRF();
1594
1595 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001596}
1597
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001598bool TWPartition::Wipe_EXFAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001599 string command;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001600
1601 if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
1602 if (!UnMount(true))
1603 return false;
1604
Dees_Troy2673cec2013-04-02 20:22:16 +00001605 gui_print("Formatting %s using mkexfatfs...\n", Display_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001606 Find_Actual_Block_Device();
1607 command = "mkexfatfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001608 if (TWFunc::Exec_Cmd(command) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001609 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001610 gui_print("Done.\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001611 return true;
1612 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001613 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001614 return false;
1615 }
1616 return true;
1617 }
1618 return false;
1619}
1620
Dees_Troy38bd7602012-09-14 13:33:53 -04001621bool TWPartition::Wipe_MTD() {
1622 if (!UnMount(true))
1623 return false;
1624
Dees_Troy2673cec2013-04-02 20:22:16 +00001625 gui_print("MTD Formatting \"%s\"\n", MTD_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001626
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001627 mtd_scan_partitions();
1628 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
1629 if (mtd == NULL) {
1630 LOGERR("No mtd partition named '%s'", MTD_Name.c_str());
1631 return false;
1632 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001633
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001634 MtdWriteContext* ctx = mtd_write_partition(mtd);
1635 if (ctx == NULL) {
1636 LOGERR("Can't write '%s', failed to format.", MTD_Name.c_str());
1637 return false;
1638 }
1639 if (mtd_erase_blocks(ctx, -1) == -1) {
1640 mtd_write_close(ctx);
1641 LOGERR("Failed to format '%s'", MTD_Name.c_str());
1642 return false;
1643 }
1644 if (mtd_write_close(ctx) != 0) {
1645 LOGERR("Failed to close '%s'", MTD_Name.c_str());
1646 return false;
1647 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001648 Current_File_System = "yaffs2";
Dees_Troye58d5262012-09-21 12:27:57 -04001649 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001650 gui_print("Done.\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001651 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001652}
1653
1654bool TWPartition::Wipe_RMRF() {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001655 if (Is_Storage)
1656 TWFunc::Toggle_MTP(false);
Dees_Troy38bd7602012-09-14 13:33:53 -04001657 if (!Mount(true))
1658 return false;
1659
Dees_Troy2673cec2013-04-02 20:22:16 +00001660 gui_print("Removing all files under '%s'\n", Mount_Point.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001661 TWFunc::removeDir(Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04001662 Recreate_AndSec_Folder();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001663 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001664}
1665
Dees_Troye5017042013-08-29 16:38:55 +00001666bool TWPartition::Wipe_F2FS() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001667 string command;
Dees_Troye5017042013-08-29 16:38:55 +00001668
1669 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
1670 if (!UnMount(true))
1671 return false;
1672
1673 gui_print("Formatting %s using mkfs.f2fs...\n", Display_Name.c_str());
1674 Find_Actual_Block_Device();
1675 command = "mkfs.f2fs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001676 if (TWFunc::Exec_Cmd(command) == 0) {
Dees_Troye5017042013-08-29 16:38:55 +00001677 Recreate_AndSec_Folder();
1678 gui_print("Done.\n");
1679 return true;
1680 } else {
1681 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
1682 return false;
1683 }
1684 return true;
1685 } else {
1686 gui_print("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
1687 return Wipe_RMRF();
1688 }
1689 return false;
1690}
1691
Dees_Troy51a0e822012-09-05 15:24:24 -04001692bool TWPartition::Wipe_Data_Without_Wiping_Media() {
Ethan Yonker83e82572014-04-04 10:59:28 -05001693#ifdef TW_OEM_BUILD
1694 // In an OEM Build we want to do a full format
1695 return Wipe_Encryption();
1696#else
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001697 string dir;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001698 #ifdef HAVE_SELINUX
1699 fixPermissions perms;
1700 #endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001701
1702 // This handles wiping data on devices with "sdcard" in /data/media
1703 if (!Mount(true))
1704 return false;
1705
Dees_Troy2673cec2013-04-02 20:22:16 +00001706 gui_print("Wiping data without wiping /data/media ...\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001707
1708 DIR* d;
1709 d = opendir("/data");
Dees_Troy16b74352012-11-14 22:27:31 +00001710 if (d != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001711 struct dirent* de;
1712 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001713 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
Dees_Troy16b74352012-11-14 22:27:31 +00001714 // The media folder is the "internal sdcard"
1715 // The .layout_version file is responsible for determining whether 4.2 decides up upgrade
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001716 // the media folder for multi-user.
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001717 //TODO: convert this to use twrpDU.cpp
Dees_Troy16b74352012-11-14 22:27:31 +00001718 if (strcmp(de->d_name, "media") == 0 || strcmp(de->d_name, ".layout_version") == 0) continue;
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001719
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001720 dir = "/data/";
1721 dir.append(de->d_name);
Dees_Troyce675462013-01-09 19:48:21 +00001722 if (de->d_type == DT_DIR) {
1723 TWFunc::removeDir(dir, false);
bigbiff bigbiff98f1f902013-01-19 18:46:13 -05001724 } else if (de->d_type == DT_REG || de->d_type == DT_LNK || de->d_type == DT_FIFO || de->d_type == DT_SOCK) {
Dees_Troyce675462013-01-09 19:48:21 +00001725 if (!unlink(dir.c_str()))
Dees_Troy2673cec2013-04-02 20:22:16 +00001726 LOGINFO("Unable to unlink '%s'\n", dir.c_str());
Dees_Troyce675462013-01-09 19:48:21 +00001727 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001728 }
1729 closedir(d);
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001730
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001731 #ifdef HAVE_SELINUX
1732 perms.fixDataInternalContexts();
1733 #endif
1734
Dees_Troy2673cec2013-04-02 20:22:16 +00001735 gui_print("Done.\n");
Dees_Troy16b74352012-11-14 22:27:31 +00001736 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04001737 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001738 gui_print("Dirent failed to open /data, error!\n");
Dees_Troy16b74352012-11-14 22:27:31 +00001739 return false;
Ethan Yonker83e82572014-04-04 10:59:28 -05001740#endif // ifdef TW_OEM_BUILD
Dees_Troy51a0e822012-09-05 15:24:24 -04001741}
1742
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001743bool TWPartition::Backup_Tar(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size) {
Dees_Troy4a2a1262012-09-18 09:33:47 -04001744 char back_name[255], split_index[5];
1745 string Full_FileName, Split_FileName, Tar_Args, Command;
Dees_Troy83bd4832013-05-04 12:39:56 +00001746 int use_compression, use_encryption = 0, index, backup_count;
Dees_Troy4a2a1262012-09-18 09:33:47 -04001747 struct stat st;
Dees_Troy7c2dec82012-09-26 09:49:14 -04001748 unsigned long long total_bsize = 0, file_size;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001749 twrpTar tar;
1750 vector <string> files;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001751
Dees_Troy43d8b002012-09-17 16:00:01 -04001752 if (!Mount(true))
1753 return false;
1754
Dees_Troya13d74f2013-03-24 08:54:55 -05001755 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001756 gui_print("Backing up %s...\n", Backup_Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001757
1758 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
Dees_Troy83bd4832013-05-04 12:39:56 +00001759 tar.use_compression = use_compression;
Matt Mowerbb81e5d2014-03-20 18:05:41 -05001760
Dees_Troy83bd4832013-05-04 12:39:56 +00001761#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
1762 DataManager::GetValue("tw_encrypt_backup", use_encryption);
1763 if (use_encryption && Can_Encrypt_Backup) {
1764 tar.use_encryption = use_encryption;
1765 if (Use_Userdata_Encryption)
1766 tar.userdata_encryption = use_encryption;
Ethan Yonker87af5632014-02-10 11:56:35 -06001767 string Password;
1768 DataManager::GetValue("tw_backup_password", Password);
1769 tar.setpassword(Password);
Dees_Troy83bd4832013-05-04 12:39:56 +00001770 } else {
1771 use_encryption = false;
1772 }
1773#endif
Dees_Troy43d8b002012-09-17 16:00:01 -04001774
1775 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1776 Backup_FileName = back_name;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001777 Full_FileName = backup_folder + "/" + Backup_FileName;
Dees_Troy83bd4832013-05-04 12:39:56 +00001778 tar.has_data_media = Has_Data_Media;
Dees Troye0a433a2013-12-02 04:10:37 +00001779 Full_FileName = backup_folder + "/" + Backup_FileName;
1780 tar.setdir(Backup_Path);
1781 tar.setfn(Full_FileName);
1782 tar.setsize(Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001783 tar.partition_name = Backup_Name;
1784 tar.backup_folder = backup_folder;
1785 if (tar.createTarFork(overall_size, other_backups_size) != 0)
Dees Troye0a433a2013-12-02 04:10:37 +00001786 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04001787 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001788}
1789
1790bool TWPartition::Backup_DD(string backup_folder) {
igoriok87e3d932013-01-31 21:03:53 +02001791 char back_name[255], backup_size[32];
Vojtech Bocek05534202013-09-11 08:11:56 +02001792 string Full_FileName, Command, DD_BS;
Dees_Troy43d8b002012-09-17 16:00:01 -04001793 int use_compression;
1794
igoriok87e3d932013-01-31 21:03:53 +02001795 sprintf(backup_size, "%llu", Backup_Size);
1796 DD_BS = backup_size;
1797
Dees_Troyb46a6842012-09-25 11:06:46 -04001798 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001799 gui_print("Backing up %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001800
1801 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1802 Backup_FileName = back_name;
1803
1804 Full_FileName = backup_folder + "/" + Backup_FileName;
1805
igoriok87e3d932013-01-31 21:03:53 +02001806 Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'" + " bs=" + DD_BS + "c count=1";
Dees_Troy2673cec2013-04-02 20:22:16 +00001807 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001808 TWFunc::Exec_Cmd(Command);
Dees_Troyc154ac22012-10-12 15:36:47 -04001809 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001810 LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04001811 return false;
1812 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001813 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001814}
1815
1816bool TWPartition::Backup_Dump_Image(string backup_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001817 char back_name[255];
Vojtech Bocek05534202013-09-11 08:11:56 +02001818 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04001819 int use_compression;
1820
Dees_Troyb46a6842012-09-25 11:06:46 -04001821 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001822 gui_print("Backing up %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001823
1824 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1825 Backup_FileName = back_name;
1826
1827 Full_FileName = backup_folder + "/" + Backup_FileName;
1828
1829 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
Dees_Troy2673cec2013-04-02 20:22:16 +00001830 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001831 TWFunc::Exec_Cmd(Command);
Dees_Troy7c2dec82012-09-26 09:49:14 -04001832 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
1833 // Actual size may not match backup size due to bad blocks on MTD devices so just check for 0 bytes
Dees_Troy2673cec2013-04-02 20:22:16 +00001834 LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04001835 return false;
1836 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001837 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001838}
1839
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001840unsigned long long TWPartition::Get_Restore_Size(string restore_folder) {
1841 InfoManager restore_info(restore_folder + "/" + Backup_Name + ".info");
1842 if (restore_info.LoadValues() == 0) {
1843 if (restore_info.GetValue("backup_size", Restore_Size) == 0) {
1844 LOGINFO("Read info file, restore size is %llu\n", Restore_Size);
1845 return Restore_Size;
1846 }
1847 }
1848 string Full_FileName, Restore_File_System = Get_Restore_File_System(restore_folder);
1849
1850 Full_FileName = restore_folder + "/" + Backup_FileName;
1851
1852 if (Is_Image(Restore_File_System)) {
1853 Restore_Size = TWFunc::Get_File_Size(Full_FileName);
1854 return Restore_Size;
1855 }
1856
1857 twrpTar tar;
1858 tar.setdir(Backup_Path);
1859 tar.setfn(Full_FileName);
1860 tar.backup_name = Backup_Name;
1861#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
1862 string Password;
1863 DataManager::GetValue("tw_restore_password", Password);
1864 if (!Password.empty())
1865 tar.setpassword(Password);
1866#endif
1867 tar.partition_name = Backup_Name;
1868 tar.backup_folder = restore_folder;
1869 Restore_Size = tar.get_size();
1870 return Restore_Size;
1871}
1872
1873bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) {
Gary Peck43acadf2012-11-21 21:19:01 -08001874 string Full_FileName, Command;
Dees_Troy4a2a1262012-09-18 09:33:47 -04001875 int index = 0;
1876 char split_index[5];
Dees Troy4159aed2014-02-28 17:24:43 +00001877 bool ret = false;
Dees_Troy43d8b002012-09-17 16:00:01 -04001878
Dees_Troye58d5262012-09-21 12:27:57 -04001879 if (Has_Android_Secure) {
Dees_Troye58d5262012-09-21 12:27:57 -04001880 if (!Wipe_AndSec())
1881 return false;
Gary Peck43acadf2012-11-21 21:19:01 -08001882 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001883 gui_print("Wiping %s...\n", Display_Name.c_str());
Ethan Yonker5eac2222014-06-11 12:22:55 -05001884 if (Has_Data_Media && Mount_Point == "/data" && Restore_File_System != Current_File_System) {
1885 gui_print("WARNING: This /data backup was made with %s file system!\n", Restore_File_System.c_str());
1886 gui_print("The backup may not boot unless you change back to %s.\n", Restore_File_System.c_str());
1887 if (!Wipe_Data_Without_Wiping_Media())
1888 return false;
1889 } else {
1890 if (!Wipe(Restore_File_System))
1891 return false;
1892 }
Dees_Troye58d5262012-09-21 12:27:57 -04001893 }
Dees_Troya13d74f2013-03-24 08:54:55 -05001894 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, "Restoring");
Dees_Troy2673cec2013-04-02 20:22:16 +00001895 gui_print("Restoring %s...\n", Backup_Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001896
1897 if (!Mount(true))
1898 return false;
1899
Dees_Troy4a2a1262012-09-18 09:33:47 -04001900 Full_FileName = restore_folder + "/" + Backup_FileName;
Ethan Yonker87af5632014-02-10 11:56:35 -06001901 twrpTar tar;
1902 tar.setdir(Backup_Path);
1903 tar.setfn(Full_FileName);
1904 tar.backup_name = Backup_Name;
1905#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
1906 string Password;
1907 DataManager::GetValue("tw_restore_password", Password);
1908 if (!Password.empty())
1909 tar.setpassword(Password);
1910#endif
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001911 if (tar.extractTarFork(total_restore_size, already_restored_size) != 0)
Dees Troy4159aed2014-02-28 17:24:43 +00001912 ret = false;
1913 else
1914 ret = true;
1915#ifdef HAVE_CAPABILITIES
1916 // Restore capabilities to the run-as binary
1917 if (Mount_Point == "/system" && Mount(true) && TWFunc::Path_Exists("/system/bin/run-as")) {
1918 struct vfs_cap_data cap_data;
1919 uint64_t capabilities = (1 << CAP_SETUID) | (1 << CAP_SETGID);
1920
1921 memset(&cap_data, 0, sizeof(cap_data));
1922 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
1923 cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
1924 cap_data.data[0].inheritable = 0;
1925 cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
1926 cap_data.data[1].inheritable = 0;
1927 if (setxattr("/system/bin/run-as", XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
1928 LOGINFO("Failed to reset capabilities of /system/bin/run-as binary.\n");
1929 } else {
1930 LOGINFO("Reset capabilities of /system/bin/run-as binary successful.\n");
1931 }
1932 }
1933#endif
1934 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001935}
1936
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001937bool TWPartition::Restore_DD(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001938 string Full_FileName, Command;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001939 double display_percent, progress_percent;
1940 char size_progress[1024];
Dees_Troy43d8b002012-09-17 16:00:01 -04001941
Dees_Troyda8b55a2012-12-12 19:18:30 +00001942 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy43d8b002012-09-17 16:00:01 -04001943 Full_FileName = restore_folder + "/" + Backup_FileName;
Gary Peck15e623d2012-11-21 21:07:58 -08001944
1945 if (!Find_Partition_Size()) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001946 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Gary Peck15e623d2012-11-21 21:07:58 -08001947 return false;
1948 }
1949 unsigned long long backup_size = TWFunc::Get_File_Size(Full_FileName);
1950 if (backup_size > Size) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001951 LOGERR("Size (%iMB) of backup '%s' is larger than target device '%s' (%iMB)\n",
Gary Peck15e623d2012-11-21 21:07:58 -08001952 (int)(backup_size / 1048576LLU), Full_FileName.c_str(),
1953 Actual_Block_Device.c_str(), (int)(Size / 1048576LLU));
1954 return false;
1955 }
1956
Dees_Troy2673cec2013-04-02 20:22:16 +00001957 gui_print("Restoring %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001958 Command = "dd bs=4096 if='" + Full_FileName + "' of=" + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001959 LOGINFO("Restore command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001960 TWFunc::Exec_Cmd(Command);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001961 display_percent = (double)(Restore_Size + *already_restored_size) / (double)(*total_restore_size) * 100;
1962 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (Restore_Size + *already_restored_size) / 1048576, *total_restore_size / 1048576, (int)(display_percent));
1963 DataManager::SetValue("tw_size_progress", size_progress);
1964 progress_percent = (display_percent / 100);
1965 DataManager::SetProgress((float)(progress_percent));
1966 *already_restored_size += Restore_Size;
Dees_Troy43d8b002012-09-17 16:00:01 -04001967 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001968}
1969
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001970bool TWPartition::Restore_Flash_Image(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001971 string Full_FileName, Command;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001972 double display_percent, progress_percent;
1973 char size_progress[1024];
Dees_Troy43d8b002012-09-17 16:00:01 -04001974
Dees_Troy2673cec2013-04-02 20:22:16 +00001975 gui_print("Restoring %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001976 Full_FileName = restore_folder + "/" + Backup_FileName;
1977 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
1978 Command = "erase_image " + MTD_Name;
Dees_Troy2673cec2013-04-02 20:22:16 +00001979 LOGINFO("Erase command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001980 TWFunc::Exec_Cmd(Command);
Dees_Troy43d8b002012-09-17 16:00:01 -04001981 Command = "flash_image " + MTD_Name + " '" + Full_FileName + "'";
Dees_Troy2673cec2013-04-02 20:22:16 +00001982 LOGINFO("Restore command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001983 TWFunc::Exec_Cmd(Command);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001984 display_percent = (double)(Restore_Size + *already_restored_size) / (double)(*total_restore_size) * 100;
1985 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (Restore_Size + *already_restored_size) / 1048576, *total_restore_size / 1048576, (int)(display_percent));
1986 DataManager::SetValue("tw_size_progress", size_progress);
1987 progress_percent = (display_percent / 100);
1988 DataManager::SetProgress((float)(progress_percent));
1989 *already_restored_size += Restore_Size;
Dees_Troy43d8b002012-09-17 16:00:01 -04001990 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001991}
Dees_Troy5bf43922012-09-07 16:07:55 -04001992
1993bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy0550cfb2012-10-13 11:56:13 -04001994 bool ret = false, Was_Already_Mounted = false;
Dees_Troy51127312012-09-08 13:08:49 -04001995
Dees_Troyab10ee22012-09-21 14:27:30 -04001996 if (!Can_Be_Mounted && !Is_Encrypted)
Dees_Troy5bf43922012-09-07 16:07:55 -04001997 return false;
1998
Dees_Troy0550cfb2012-10-13 11:56:13 -04001999 Was_Already_Mounted = Is_Mounted();
Dees_Troy38bd7602012-09-14 13:33:53 -04002000 if (Removable || Is_Encrypted) {
2001 if (!Mount(false))
2002 return true;
2003 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04002004 return false;
Dees_Troy51127312012-09-08 13:08:49 -04002005
2006 ret = Get_Size_Via_statfs(Display_Error);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002007 if (!ret || Size == 0) {
2008 if (!Get_Size_Via_df(Display_Error)) {
2009 if (!Was_Already_Mounted)
2010 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -04002011 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002012 }
2013 }
Dees_Troy51127312012-09-08 13:08:49 -04002014
Dees_Troy5bf43922012-09-07 16:07:55 -04002015 if (Has_Data_Media) {
2016 if (Mount(Display_Error)) {
Dees_Troy51127312012-09-08 13:08:49 -04002017 unsigned long long data_media_used, actual_data;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002018 Used = du.Get_Folder_Size("/data");
2019 Backup_Size = Used;
2020 int bak = (int)(Used / 1048576LLU);
Dees_Troy51127312012-09-08 13:08:49 -04002021 int fre = (int)(Free / 1048576LLU);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002022 LOGINFO("Data backup size is %iMB, free: %iMB.\n", bak, fre);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002023 } else {
2024 if (!Was_Already_Mounted)
2025 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002026 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002027 }
Dees_Troye58d5262012-09-21 12:27:57 -04002028 } else if (Has_Android_Secure) {
2029 if (Mount(Display_Error))
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05002030 Backup_Size = du.Get_Folder_Size(Backup_Path);
Dees_Troy0550cfb2012-10-13 11:56:13 -04002031 else {
2032 if (!Was_Already_Mounted)
2033 UnMount(false);
Dees_Troye58d5262012-09-21 12:27:57 -04002034 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04002035 }
Dees_Troy5bf43922012-09-07 16:07:55 -04002036 }
Dees_Troy0550cfb2012-10-13 11:56:13 -04002037 if (!Was_Already_Mounted)
2038 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04002039 return true;
Dees_Troy51127312012-09-08 13:08:49 -04002040}
Dees_Troy38bd7602012-09-14 13:33:53 -04002041
2042void TWPartition::Find_Actual_Block_Device(void) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04002043 if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002044 Actual_Block_Device = Decrypted_Block_Device;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04002045 if (TWFunc::Path_Exists(Decrypted_Block_Device))
Dees_Troy38bd7602012-09-14 13:33:53 -04002046 Is_Present = true;
Dees_Troy43d8b002012-09-17 16:00:01 -04002047 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04002048 Is_Present = true;
2049 Actual_Block_Device = Primary_Block_Device;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002050 return;
2051 }
2052 if (Is_Decrypted) {
Dees_Troy43d8b002012-09-17 16:00:01 -04002053 } else if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy3f04d032012-10-07 18:20:09 -04002054 Actual_Block_Device = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -04002055 Is_Present = true;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002056 } else {
Dees_Troy38bd7602012-09-14 13:33:53 -04002057 Is_Present = false;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002058 }
Dees_Troy38bd7602012-09-14 13:33:53 -04002059}
2060
2061void TWPartition::Recreate_Media_Folder(void) {
2062 string Command;
2063
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05002064 #ifdef HAVE_SELINUX
2065 fixPermissions perms;
2066 #endif
2067
Dees_Troy38bd7602012-09-14 13:33:53 -04002068 if (!Mount(true)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002069 LOGERR("Unable to recreate /data/media folder.\n");
Dees_Troyb46a6842012-09-25 11:06:46 -04002070 } else if (!TWFunc::Path_Exists("/data/media")) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002071 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy2673cec2013-04-02 20:22:16 +00002072 LOGINFO("Recreating /data/media folder.\n");
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05002073 mkdir("/data/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05002074 #ifdef HAVE_SELINUX
2075 perms.fixDataInternalContexts();
2076 #endif
Ethan Yonker5eac2222014-06-11 12:22:55 -05002077 // Toggle mount to ensure that "internal sdcard" gets mounted
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002078 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Ethan Yonker5eac2222014-06-11 12:22:55 -05002079 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy38bd7602012-09-14 13:33:53 -04002080 }
Dees_Troy43d8b002012-09-17 16:00:01 -04002081}
Dees_Troye58d5262012-09-21 12:27:57 -04002082
2083void TWPartition::Recreate_AndSec_Folder(void) {
Dees_Troye58d5262012-09-21 12:27:57 -04002084 if (!Has_Android_Secure)
2085 return;
Dees_Troy2673cec2013-04-02 20:22:16 +00002086 LOGINFO("Creating %s: %s\n", Backup_Display_Name.c_str(), Symlink_Path.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04002087 if (!Mount(true)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002088 LOGERR("Unable to recreate %s folder.\n", Backup_Name.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04002089 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00002090 LOGINFO("Recreating %s folder.\n", Backup_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002091 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05002092 mkdir(Symlink_Path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002093 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04002094 }
2095}