blob: 57a692349e56d2c6504667093c2a55145d638969 [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"
Dees_Troy5bf43922012-09-07 16:07:55 -040044extern "C" {
Dees_Troy38bd7602012-09-14 13:33:53 -040045 #include "mtdutils/mtdutils.h"
46 #include "mtdutils/mounts.h"
Dees_Troy85f44ed2013-01-09 18:42:36 +000047#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
48 #include "crypto/libcrypt_samsung/include/libcrypt_samsung.h"
49#endif
Dees_Troya95f55c2013-08-17 13:14:43 +000050#ifdef USE_EXT4
51 #include "make_ext4fs.h"
52#endif
Ethan Yonker71413f42014-02-26 13:36:08 -060053
54#ifdef TW_INCLUDE_CRYPTO
55 #ifdef TW_INCLUDE_JB_CRYPTO
56 #include "crypto/jb/cryptfs.h"
57 #else
58 #include "crypto/ics/cryptfs.h"
59 #endif
60#endif
Dees_Troy5bf43922012-09-07 16:07:55 -040061}
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040062#ifdef HAVE_SELINUX
63#include "selinux/selinux.h"
Ethan Yonkerf27497f2014-02-09 11:48:33 -060064#include <selinux/label.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040065#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040066
bigbiff bigbiff9c754052013-01-09 09:09:08 -050067using namespace std;
68
Dees_Troya95f55c2013-08-17 13:14:43 +000069extern struct selabel_handle *selinux_handle;
70
Hashcode62bd9e02013-11-19 21:59:42 -080071struct flag_list {
72 const char *name;
73 unsigned flag;
74};
75
76static struct flag_list mount_flags[] = {
77 { "noatime", MS_NOATIME },
78 { "noexec", MS_NOEXEC },
79 { "nosuid", MS_NOSUID },
80 { "nodev", MS_NODEV },
81 { "nodiratime", MS_NODIRATIME },
82 { "ro", MS_RDONLY },
83 { "rw", 0 },
84 { "remount", MS_REMOUNT },
85 { "bind", MS_BIND },
86 { "rec", MS_REC },
Dees Troyc4bc30e2014-02-03 15:04:19 +000087#ifdef MS_UNBINDABLE
Hashcode62bd9e02013-11-19 21:59:42 -080088 { "unbindable", MS_UNBINDABLE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000089#endif
90#ifdef MS_PRIVATE
Hashcode62bd9e02013-11-19 21:59:42 -080091 { "private", MS_PRIVATE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000092#endif
93#ifdef MS_SLAVE
Hashcode62bd9e02013-11-19 21:59:42 -080094 { "slave", MS_SLAVE },
Dees Troyc4bc30e2014-02-03 15:04:19 +000095#endif
96#ifdef MS_SHARED
Hashcode62bd9e02013-11-19 21:59:42 -080097 { "shared", MS_SHARED },
Dees Troyc4bc30e2014-02-03 15:04:19 +000098#endif
Hashcode62bd9e02013-11-19 21:59:42 -080099 { "sync", MS_SYNCHRONOUS },
100 { "defaults", 0 },
101 { 0, 0 },
102};
103
Dees_Troy51a0e822012-09-05 15:24:24 -0400104TWPartition::TWPartition(void) {
105 Can_Be_Mounted = false;
106 Can_Be_Wiped = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500107 Can_Be_Backed_Up = false;
Vojtech Bocek1dc30982013-08-30 21:49:30 +0200108 Use_Rm_Rf = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400109 Wipe_During_Factory_Reset = false;
110 Wipe_Available_in_GUI = false;
111 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -0400112 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400113 SubPartition_Of = "";
114 Symlink_Path = "";
115 Symlink_Mount_Point = "";
116 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -0400117 Backup_Path = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400118 Actual_Block_Device = "";
119 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400120 Alternate_Block_Device = "";
121 Removable = false;
122 Is_Present = false;
123 Length = 0;
124 Size = 0;
125 Used = 0;
126 Free = 0;
127 Backup_Size = 0;
128 Can_Be_Encrypted = false;
129 Is_Encrypted = false;
130 Is_Decrypted = false;
131 Decrypted_Block_Device = "";
132 Display_Name = "";
Dees_Troya13d74f2013-03-24 08:54:55 -0500133 Backup_Display_Name = "";
134 Storage_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400135 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -0400136 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -0400137 MTD_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400138 Backup_Method = NONE;
Dees_Troy83bd4832013-05-04 12:39:56 +0000139 Can_Encrypt_Backup = false;
140 Use_Userdata_Encryption = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400141 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -0400142 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400143 Is_Storage = false;
Dees_Troya13d74f2013-03-24 08:54:55 -0500144 Is_Settings_Storage = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400145 Storage_Path = "";
146 Current_File_System = "";
147 Fstab_File_System = "";
Hashcode62bd9e02013-11-19 21:59:42 -0800148 Mount_Flags = 0;
149 Mount_Options = "";
Dees_Troy51a0e822012-09-05 15:24:24 -0400150 Format_Block_Size = 0;
Dees_Troy68cab492012-12-12 19:29:35 +0000151 Ignore_Blkid = false;
Dees_Troy16c2b312013-01-15 16:51:18 +0000152 Retain_Layout_Version = false;
Dees_Troy85f44ed2013-01-09 18:42:36 +0000153#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
154 EcryptFS_Password = "";
155#endif
Dees_Troy51a0e822012-09-05 15:24:24 -0400156}
157
158TWPartition::~TWPartition(void) {
159 // Do nothing
160}
161
Dees_Troy5bf43922012-09-07 16:07:55 -0400162bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
163 char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH];
164 int line_len = Line.size(), index = 0, item_index = 0;
165 char* ptr;
Dees_Troy51127312012-09-08 13:08:49 -0400166 string Flags;
Dees_Troy5bf43922012-09-07 16:07:55 -0400167 strncpy(full_line, Line.c_str(), line_len);
Dees_Troya13d74f2013-03-24 08:54:55 -0500168 bool skip = false;
Dees_Troy5bf43922012-09-07 16:07:55 -0400169
Dees_Troy51127312012-09-08 13:08:49 -0400170 for (index = 0; index < line_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500171 if (full_line[index] == 34)
172 skip = !skip;
173 if (!skip && full_line[index] <= 32)
Dees_Troy5bf43922012-09-07 16:07:55 -0400174 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400175 }
Dees_Troy7c2dec82012-09-26 09:49:14 -0400176 Mount_Point = full_line;
Dees_Troy2673cec2013-04-02 20:22:16 +0000177 LOGINFO("Processing '%s'\n", Mount_Point.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -0400178 Backup_Path = Mount_Point;
Dees_Troya13d74f2013-03-24 08:54:55 -0500179 Storage_Path = Mount_Point;
Dees_Troy70737fa2013-04-08 13:19:20 +0000180 Display_Name = full_line + 1;
181 Backup_Display_Name = Display_Name;
182 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400183 index = Mount_Point.size();
184 while (index < line_len) {
185 while (index < line_len && full_line[index] == '\0')
186 index++;
187 if (index >= line_len)
188 continue;
189 ptr = full_line + index;
190 if (item_index == 0) {
191 // File System
192 Fstab_File_System = ptr;
193 Current_File_System = ptr;
194 item_index++;
195 } else if (item_index == 1) {
196 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400197 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
Dees_Troy094207a2012-09-26 12:00:39 -0400198 MTD_Name = ptr;
199 Find_MTD_Block_Device(MTD_Name);
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400200 } else if (Fstab_File_System == "bml") {
201 if (Mount_Point == "/boot")
202 MTD_Name = "boot";
203 else if (Mount_Point == "/recovery")
204 MTD_Name = "recovery";
205 Primary_Block_Device = ptr;
206 if (*ptr != '/')
Dees_Troy2673cec2013-04-02 20:22:16 +0000207 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 -0400208 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400209 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000210 LOGERR("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400211 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000212 LOGINFO("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
Dees_Troy5bf43922012-09-07 16:07:55 -0400213 return 0;
Dees_Troy38bd7602012-09-14 13:33:53 -0400214 } else {
215 Primary_Block_Device = ptr;
216 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400217 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400218 item_index++;
219 } else if (item_index > 1) {
220 if (*ptr == '/') {
221 // Alternate Block Device
222 Alternate_Block_Device = ptr;
223 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
224 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
225 // Partition length
226 ptr += 7;
227 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400228 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
229 // Custom flags, save for later so that new values aren't overwritten by defaults
230 ptr += 6;
231 Flags = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000232 Process_Flags(Flags, Display_Error);
Dees_Troy38bd7602012-09-14 13:33:53 -0400233 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
234 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400235 } else {
236 // Unhandled data
Dees_Troy2673cec2013-04-02 20:22:16 +0000237 LOGINFO("Unhandled fstab information: '%s', %i, line: '%s'\n", ptr, index, Line.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400238 }
239 }
240 while (index < line_len && full_line[index] != '\0')
241 index++;
242 }
243
244 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
245 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000246 LOGERR("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400247 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000248 LOGINFO("Unknown File System: '%s'\n", Fstab_File_System.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400249 return 0;
250 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400251 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400252 Setup_File_System(Display_Error);
253 if (Mount_Point == "/system") {
254 Display_Name = "System";
Dees_Troya13d74f2013-03-24 08:54:55 -0500255 Backup_Display_Name = Display_Name;
256 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400257 Wipe_Available_in_GUI = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500258 Can_Be_Backed_Up = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400259 } else if (Mount_Point == "/data") {
260 Display_Name = "Data";
Dees_Troya13d74f2013-03-24 08:54:55 -0500261 Backup_Display_Name = Display_Name;
262 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400263 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400264 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500265 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000266 Can_Encrypt_Backup = true;
267 Use_Userdata_Encryption = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400268#ifdef RECOVERY_SDCARD_ON_DATA
Dees_Troya13d74f2013-03-24 08:54:55 -0500269 Storage_Name = "Internal Storage";
Dees_Troy5bf43922012-09-07 16:07:55 -0400270 Has_Data_Media = true;
Dees_Troy51127312012-09-08 13:08:49 -0400271 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500272 Is_Settings_Storage = true;
Dees_Troy51127312012-09-08 13:08:49 -0400273 Storage_Path = "/data/media";
Dees_Troy16b74352012-11-14 22:27:31 +0000274 Symlink_Path = Storage_Path;
Dees_Troy657c3092012-09-10 20:32:10 -0400275 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
276 Make_Dir("/emmc", Display_Error);
Dees_Troy657c3092012-09-10 20:32:10 -0400277 Symlink_Mount_Point = "/emmc";
278 } else {
279 Make_Dir("/sdcard", Display_Error);
Dees_Troy657c3092012-09-10 20:32:10 -0400280 Symlink_Mount_Point = "/sdcard";
281 }
Dees_Troy16b74352012-11-14 22:27:31 +0000282 if (Mount(false) && TWFunc::Path_Exists("/data/media/0")) {
283 Storage_Path = "/data/media/0";
284 Symlink_Path = Storage_Path;
285 DataManager::SetValue(TW_INTERNAL_PATH, "/data/media/0");
286 UnMount(true);
287 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400288#endif
289#ifdef TW_INCLUDE_CRYPTO
290 Can_Be_Encrypted = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400291 char crypto_blkdev[255];
292 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
293 if (strcmp(crypto_blkdev, "error") != 0) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400294 DataManager::SetValue(TW_DATA_BLK_DEVICE, Primary_Block_Device);
Dees_Troy657c3092012-09-10 20:32:10 -0400295 DataManager::SetValue(TW_IS_DECRYPTED, 1);
296 Is_Encrypted = true;
297 Is_Decrypted = true;
298 Decrypted_Block_Device = crypto_blkdev;
Dees_Troy2673cec2013-04-02 20:22:16 +0000299 LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
Dees_Troy657c3092012-09-10 20:32:10 -0400300 } else if (!Mount(false)) {
Ethan Yonker71413f42014-02-26 13:36:08 -0600301 if (Is_Present) {
302#ifdef TW_INCLUDE_JB_CRYPTO
303 // No extra flags needed
304#else
305 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
306 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
307 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
308 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
309 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
310 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
311#ifdef CRYPTO_SD_FS_TYPE
312 property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
313 property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
314 property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
315#endif
316 property_set("rw.km_fips_status", "ready");
317#endif
318 if (cryptfs_check_footer() == 0) {
319 Is_Encrypted = true;
320 Is_Decrypted = false;
321 Can_Be_Mounted = false;
322 Current_File_System = "emmc";
323 Setup_Image(Display_Error);
324 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
325 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
326 DataManager::SetValue("tw_crypto_display", "");
327 } else {
328 LOGERR("Could not mount /data and unable to find crypto footer.\n");
329 }
330 } else {
331 LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
332 }
Gary Peck82599a82012-11-21 16:23:12 -0800333 } else {
334 // Filesystem is not encrypted and the mount
335 // succeeded, so get it back to the original
336 // unmounted state
337 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -0400338 }
Dees_Troy9b21af72012-10-01 15:51:46 -0400339 #ifdef RECOVERY_SDCARD_ON_DATA
340 if (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))
341 Recreate_Media_Folder();
342 #endif
343#else
344 #ifdef RECOVERY_SDCARD_ON_DATA
345 Recreate_Media_Folder();
346 #endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400347#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400348 } else if (Mount_Point == "/cache") {
349 Display_Name = "Cache";
Dees_Troya13d74f2013-03-24 08:54:55 -0500350 Backup_Display_Name = Display_Name;
351 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400352 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400353 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500354 Can_Be_Backed_Up = true;
Dees_Troyce2fe772012-09-28 12:34:33 -0400355 if (Mount(false) && !TWFunc::Path_Exists("/cache/recovery/.")) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000356 LOGINFO("Recreating /cache/recovery folder.\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500357 if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
358 return -1;
Dees_Troyb46a6842012-09-25 11:06:46 -0400359 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400360 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400361 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400362 Display_Name = "DataData";
Dees_Troya13d74f2013-03-24 08:54:55 -0500363 Backup_Display_Name = Display_Name;
364 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400365 Is_SubPartition = true;
366 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400367 DataManager::SetValue(TW_HAS_DATADATA, 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500368 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000369 Can_Encrypt_Backup = true;
370 Use_Userdata_Encryption = false; // This whole partition should be encrypted
Dees_Troy5bf43922012-09-07 16:07:55 -0400371 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400372 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400373 Display_Name = "SD-Ext";
Dees_Troya13d74f2013-03-24 08:54:55 -0500374 Backup_Display_Name = Display_Name;
375 Storage_Name = Display_Name;
Dees_Troy5bf43922012-09-07 16:07:55 -0400376 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400377 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500378 Can_Be_Backed_Up = true;
Dees_Troy83bd4832013-05-04 12:39:56 +0000379 Can_Encrypt_Backup = true;
380 Use_Userdata_Encryption = true;
Dees_Troy2c50e182012-09-26 20:05:28 -0400381 } else if (Mount_Point == "/boot") {
382 Display_Name = "Boot";
Dees_Troya13d74f2013-03-24 08:54:55 -0500383 Backup_Display_Name = Display_Name;
Dees_Troy2c50e182012-09-26 20:05:28 -0400384 DataManager::SetValue("tw_boot_is_mountable", 1);
Dees_Troya13d74f2013-03-24 08:54:55 -0500385 Can_Be_Backed_Up = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400386 }
387#ifdef TW_EXTERNAL_STORAGE_PATH
388 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
389 Is_Storage = true;
390 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
Dees_Troyc51f1f92012-09-20 15:32:13 -0400391 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500392 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400393#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000394 if (Mount_Point == "/sdcard" || Mount_Point == "/external_sd" || Mount_Point == "/external_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400395 Is_Storage = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400396 Removable = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500397 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400398#endif
Dees_Troyb05ddee2013-01-28 20:24:50 +0000399 }
Dees_Troy8170a922012-09-18 15:40:25 -0400400#ifdef TW_INTERNAL_STORAGE_PATH
401 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
402 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500403 Is_Settings_Storage = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400404 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troya13d74f2013-03-24 08:54:55 -0500405 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400406 }
407#else
Dees_Troy70737fa2013-04-08 13:19:20 +0000408 if (Mount_Point == "/emmc" || Mount_Point == "/internal_sd" || Mount_Point == "/internal_sdcard") {
Dees_Troy8170a922012-09-18 15:40:25 -0400409 Is_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500410 Is_Settings_Storage = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500411 Wipe_Available_in_GUI = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400412 }
413#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400414 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400415 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400416 Setup_Image(Display_Error);
Dees_Troya13d74f2013-03-24 08:54:55 -0500417 if (Mount_Point == "/boot") {
418 Display_Name = "Boot";
419 Backup_Display_Name = Display_Name;
420 Can_Be_Backed_Up = true;
421 } else if (Mount_Point == "/recovery") {
422 Display_Name = "Recovery";
423 Backup_Display_Name = Display_Name;
Dees_Troya13d74f2013-03-24 08:54:55 -0500424 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400425 }
426
Dees_Troy51127312012-09-08 13:08:49 -0400427 // Process any custom flags
428 if (Flags.size() > 0)
429 Process_Flags(Flags, Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400430 return true;
431}
432
Hashcode62bd9e02013-11-19 21:59:42 -0800433bool TWPartition::Process_FS_Flags(string& Options, int Flags) {
434 int i;
435 char *p;
436 char *savep;
437 char fs_options[250];
438
439 strlcpy(fs_options, Options.c_str(), sizeof(fs_options));
440 Options = "";
441
442 p = strtok_r(fs_options, ",", &savep);
443 while (p) {
444 /* Look for the flag "p" in the flag list "fl"
445 * If not found, the loop exits with fl[i].name being null.
446 */
447 for (i = 0; mount_flags[i].name; i++) {
448 if (strncmp(p, mount_flags[i].name, strlen(mount_flags[i].name)) == 0) {
449 Flags |= mount_flags[i].flag;
450 break;
451 }
452 }
453
454 if (!mount_flags[i].name) {
455 if (Options.size() > 0)
456 Options += ",";
457 Options += p;
458 }
459 p = strtok_r(NULL, ",", &savep);
460 }
461
462 return true;
463}
464
Dees_Troy51127312012-09-08 13:08:49 -0400465bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
466 char flags[MAX_FSTAB_LINE_LENGTH];
Dees_Troya13d74f2013-03-24 08:54:55 -0500467 int flags_len, index = 0, ptr_len;
Dees_Troy51127312012-09-08 13:08:49 -0400468 char* ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500469 bool skip = false, has_display_name = false, has_storage_name = false, has_backup_name = false;
Dees_Troy51127312012-09-08 13:08:49 -0400470
471 strcpy(flags, Flags.c_str());
472 flags_len = Flags.size();
473 for (index = 0; index < flags_len; index++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500474 if (flags[index] == 34)
475 skip = !skip;
476 if (!skip && flags[index] == ';')
Dees_Troy51127312012-09-08 13:08:49 -0400477 flags[index] = '\0';
478 }
479
480 index = 0;
481 while (index < flags_len) {
482 while (index < flags_len && flags[index] == '\0')
483 index++;
484 if (index >= flags_len)
485 continue;
486 ptr = flags + index;
Dees_Troya13d74f2013-03-24 08:54:55 -0500487 ptr_len = strlen(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400488 if (strcmp(ptr, "removable") == 0) {
489 Removable = true;
Ethan Yonker06c3f932014-02-02 22:11:14 -0600490 } else if (strncmp(ptr, "storage", 7) == 0) {
491 if (ptr_len == 7) {
Ethan Yonker06c3f932014-02-02 22:11:14 -0600492 Is_Storage = true;
493 } else if (ptr_len == 9) {
494 ptr += 9;
495 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
496 LOGINFO("storage set to true\n");
497 Is_Storage = true;
498 } else {
499 LOGINFO("storage set to false\n");
500 Is_Storage = false;
501 }
502 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500503 } else if (strcmp(ptr, "settingsstorage") == 0) {
504 Is_Storage = true;
Dees_Troy63c8df72012-09-10 14:02:05 -0400505 } else if (strcmp(ptr, "canbewiped") == 0) {
506 Can_Be_Wiped = true;
Hashcodedabfd492013-08-29 22:45:30 -0700507 } else if (strcmp(ptr, "usermrf") == 0) {
508 Use_Rm_Rf = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500509 } else if (ptr_len > 7 && strncmp(ptr, "backup=", 7) == 0) {
510 ptr += 7;
511 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
512 Can_Be_Backed_Up = true;
513 else
514 Can_Be_Backed_Up = false;
Dees_Troy63c8df72012-09-10 14:02:05 -0400515 } else if (strcmp(ptr, "wipeingui") == 0) {
516 Can_Be_Wiped = true;
517 Wipe_Available_in_GUI = true;
518 } else if (strcmp(ptr, "wipeduringfactoryreset") == 0) {
519 Can_Be_Wiped = true;
520 Wipe_Available_in_GUI = true;
521 Wipe_During_Factory_Reset = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500522 } else if (ptr_len > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) {
Dees_Troy2c4c26f2013-01-28 15:26:43 +0000523 ptr += 15;
Dees_Troy51127312012-09-08 13:08:49 -0400524 Is_SubPartition = true;
525 SubPartition_Of = ptr;
Dees_Troy68cab492012-12-12 19:29:35 +0000526 } else if (strcmp(ptr, "ignoreblkid") == 0) {
527 Ignore_Blkid = true;
Dees_Troy16c2b312013-01-15 16:51:18 +0000528 } else if (strcmp(ptr, "retainlayoutversion") == 0) {
529 Retain_Layout_Version = true;
Dees_Troya13d74f2013-03-24 08:54:55 -0500530 } else if (ptr_len > 8 && strncmp(ptr, "symlink=", 8) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400531 ptr += 8;
532 Symlink_Path = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500533 } else if (ptr_len > 8 && strncmp(ptr, "display=", 8) == 0) {
534 has_display_name = true;
Dees_Troy51127312012-09-08 13:08:49 -0400535 ptr += 8;
Dees_Troya13d74f2013-03-24 08:54:55 -0500536 if (*ptr == '\"') ptr++;
Dees_Troy51127312012-09-08 13:08:49 -0400537 Display_Name = ptr;
Dees_Troya13d74f2013-03-24 08:54:55 -0500538 if (Display_Name.substr(Display_Name.size() - 1, 1) == "\"") {
539 Display_Name.resize(Display_Name.size() - 1);
540 }
541 } else if (ptr_len > 11 && strncmp(ptr, "storagename=", 11) == 0) {
542 has_storage_name = true;
543 ptr += 11;
544 if (*ptr == '\"') ptr++;
545 Storage_Name = ptr;
546 if (Storage_Name.substr(Storage_Name.size() - 1, 1) == "\"") {
547 Storage_Name.resize(Storage_Name.size() - 1);
548 }
549 } else if (ptr_len > 11 && strncmp(ptr, "backupname=", 10) == 0) {
550 has_backup_name = true;
551 ptr += 10;
552 if (*ptr == '\"') ptr++;
553 Backup_Display_Name = ptr;
554 if (Backup_Display_Name.substr(Backup_Display_Name.size() - 1, 1) == "\"") {
555 Backup_Display_Name.resize(Backup_Display_Name.size() - 1);
556 }
557 } else if (ptr_len > 10 && strncmp(ptr, "blocksize=", 10) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400558 ptr += 10;
559 Format_Block_Size = atoi(ptr);
Dees_Troya13d74f2013-03-24 08:54:55 -0500560 } else if (ptr_len > 7 && strncmp(ptr, "length=", 7) == 0) {
Dees_Troy51127312012-09-08 13:08:49 -0400561 ptr += 7;
562 Length = atoi(ptr);
Dees_Troy83bd4832013-05-04 12:39:56 +0000563 } else if (ptr_len > 17 && strncmp(ptr, "canencryptbackup=", 17) == 0) {
564 ptr += 17;
565 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
566 Can_Encrypt_Backup = true;
567 else
568 Can_Encrypt_Backup = false;
569 } else if (ptr_len > 21 && strncmp(ptr, "userdataencryptbackup=", 21) == 0) {
570 ptr += 21;
571 if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
572 Can_Encrypt_Backup = true;
573 Use_Userdata_Encryption = true;
574 } else {
575 Use_Userdata_Encryption = false;
576 }
Hashcode62bd9e02013-11-19 21:59:42 -0800577 } else if (ptr_len > 8 && strncmp(ptr, "fsflags=", 8) == 0) {
578 ptr += 8;
579 if (*ptr == '\"') ptr++;
580
581 Mount_Options = ptr;
582 if (Mount_Options.substr(Mount_Options.size() - 1, 1) == "\"") {
583 Mount_Options.resize(Mount_Options.size() - 1);
584 }
585 Process_FS_Flags(Mount_Options, Mount_Flags);
Dees_Troy51127312012-09-08 13:08:49 -0400586 } else {
587 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000588 LOGERR("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400589 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000590 LOGINFO("Unhandled flag: '%s'\n", ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400591 }
592 while (index < flags_len && flags[index] != '\0')
593 index++;
594 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500595 if (has_display_name && !has_storage_name)
596 Storage_Name = Display_Name;
597 if (!has_display_name && has_storage_name)
598 Display_Name = Storage_Name;
Dees_Troy74fb2e92013-04-15 14:35:47 +0000599 if (has_display_name && !has_backup_name && Backup_Display_Name != "Android Secure")
Dees_Troya13d74f2013-03-24 08:54:55 -0500600 Backup_Display_Name = Display_Name;
601 if (!has_display_name && has_backup_name)
602 Display_Name = Backup_Display_Name;
Dees_Troy51127312012-09-08 13:08:49 -0400603 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400604}
605
Dees_Troy5bf43922012-09-07 16:07:55 -0400606bool TWPartition::Is_File_System(string File_System) {
607 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400608 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400609 File_System == "ext4" ||
610 File_System == "vfat" ||
611 File_System == "ntfs" ||
612 File_System == "yaffs2" ||
bigbiff bigbiff3e146522012-11-14 14:32:59 -0500613 File_System == "exfat" ||
Dees_Troye5017042013-08-29 16:38:55 +0000614 File_System == "f2fs" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400615 File_System == "auto")
616 return true;
617 else
618 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400619}
620
Dees_Troy5bf43922012-09-07 16:07:55 -0400621bool TWPartition::Is_Image(string File_System) {
Dees_Troy5fcd8f92012-10-16 12:22:05 -0400622 if (File_System == "emmc" || File_System == "mtd" || File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400623 return true;
624 else
625 return false;
626}
627
Dees_Troy51127312012-09-08 13:08:49 -0400628bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400629 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400630 if (mkdir(Path.c_str(), 0777) == -1) {
631 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000632 LOGERR("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400633 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000634 LOGINFO("Can not create '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400635 return false;
636 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000637 LOGINFO("Created '%s' folder.\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400638 return true;
639 }
640 }
641 return true;
642}
643
Dees_Troy5bf43922012-09-07 16:07:55 -0400644void TWPartition::Setup_File_System(bool Display_Error) {
645 struct statfs st;
646
647 Can_Be_Mounted = true;
648 Can_Be_Wiped = true;
649
Dees_Troy5bf43922012-09-07 16:07:55 -0400650 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400651 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400652 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
653 Backup_Name = Display_Name;
654 Backup_Method = FILES;
655}
656
657void TWPartition::Setup_Image(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400658 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
659 Backup_Name = Display_Name;
Gary Peck82599a82012-11-21 16:23:12 -0800660 if (Current_File_System == "emmc")
Dees_Troy5bf43922012-09-07 16:07:55 -0400661 Backup_Method = DD;
Gary Peck82599a82012-11-21 16:23:12 -0800662 else if (Current_File_System == "mtd" || Current_File_System == "bml")
Dees_Troy5bf43922012-09-07 16:07:55 -0400663 Backup_Method = FLASH_UTILS;
664 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000665 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 -0400666 if (Find_Partition_Size()) {
667 Used = Size;
668 Backup_Size = Size;
Dees_Troy51a0e822012-09-05 15:24:24 -0400669 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400670 if (Display_Error)
Dees Troyd932ce12013-10-18 17:12:59 +0000671 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400672 else
Dees Troyd932ce12013-10-18 17:12:59 +0000673 LOGINFO("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400674 }
675}
676
Dees_Troye58d5262012-09-21 12:27:57 -0400677void TWPartition::Setup_AndSec(void) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500678 Backup_Display_Name = "Android Secure";
Dees_Troye58d5262012-09-21 12:27:57 -0400679 Backup_Name = "and-sec";
Dees_Troya13d74f2013-03-24 08:54:55 -0500680 Can_Be_Backed_Up = true;
Dees_Troye58d5262012-09-21 12:27:57 -0400681 Has_Android_Secure = true;
682 Symlink_Path = Mount_Point + "/.android_secure";
683 Symlink_Mount_Point = "/and-sec";
684 Backup_Path = Symlink_Mount_Point;
685 Make_Dir("/and-sec", true);
686 Recreate_AndSec_Folder();
Ethan Yonkerd4d10732014-02-03 15:27:52 -0600687 Mount_Storage_Retry();
Dees_Troye58d5262012-09-21 12:27:57 -0400688}
689
Dees_Troy5bf43922012-09-07 16:07:55 -0400690void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
691 char device[512], realDevice[512];
692
693 strcpy(device, Block.c_str());
694 memset(realDevice, 0, sizeof(realDevice));
695 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
696 {
697 strcpy(device, realDevice);
698 memset(realDevice, 0, sizeof(realDevice));
699 }
700
701 if (device[0] != '/') {
702 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000703 LOGERR("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400704 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000705 LOGINFO("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400706 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400707 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400708 Block = device;
709 return;
710 }
711}
712
Dees_Troy8e337f32012-10-13 22:07:49 -0400713void TWPartition::Mount_Storage_Retry(void) {
714 // On some devices, storage doesn't want to mount right away, retry and sleep
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500715 if (!Mount(true)) {
Dees_Troy8e337f32012-10-13 22:07:49 -0400716 int retry_count = 5;
717 while (retry_count > 0 && !Mount(false)) {
718 usleep(500000);
719 retry_count--;
720 }
721 Mount(true);
722 }
723}
724
Dees_Troy38bd7602012-09-14 13:33:53 -0400725bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
726 FILE *fp = NULL;
727 char line[255];
728
729 fp = fopen("/proc/mtd", "rt");
730 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000731 LOGERR("Device does not support /proc/mtd\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400732 return false;
733 }
734
735 while (fgets(line, sizeof(line), fp) != NULL)
736 {
737 char device[32], label[32];
738 unsigned long size = 0;
739 char* fstype = NULL;
740 int deviceId;
741
742 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
743
744 // Skip header and blank lines
745 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
746 continue;
747
748 // Strip off the trailing " from the label
749 label[strlen(label)-1] = '\0';
750
751 if (strcmp(label, MTD_Name.c_str()) == 0) {
752 // We found our device
753 // Strip off the trailing : from the device
754 device[strlen(device)-1] = '\0';
755 if (sscanf(device,"mtd%d", &deviceId) == 1) {
756 sprintf(device, "/dev/block/mtdblock%d", deviceId);
757 Primary_Block_Device = device;
Dees_Troy76543db2013-06-19 16:24:30 +0000758 fclose(fp);
759 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400760 }
761 }
762 }
763 fclose(fp);
764
765 return false;
766}
767
Dees_Troy51127312012-09-08 13:08:49 -0400768bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
769 struct statfs st;
770 string Local_Path = Mount_Point + "/.";
771
772 if (!Mount(Display_Error))
773 return false;
774
775 if (statfs(Local_Path.c_str(), &st) != 0) {
776 if (!Removable) {
777 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000778 LOGERR("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400779 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000780 LOGINFO("Unable to statfs '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400781 }
782 return false;
783 }
784 Size = (st.f_blocks * st.f_bsize);
785 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
786 Free = (st.f_bfree * st.f_bsize);
787 Backup_Size = Used;
788 return true;
789}
790
791bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400792 FILE* fp;
793 char command[255], line[512];
794 int include_block = 1;
795 unsigned int min_len;
796
797 if (!Mount(Display_Error))
798 return false;
799
Dees_Troy38bd7602012-09-14 13:33:53 -0400800 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -0400801 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +0200802 TWFunc::Exec_Cmd(command);
Dees_Troy51127312012-09-08 13:08:49 -0400803 fp = fopen("/tmp/dfoutput.txt", "rt");
804 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000805 LOGINFO("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400806 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400807 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400808
809 while (fgets(line, sizeof(line), fp) != NULL)
810 {
811 unsigned long blocks, used, available;
812 char device[64];
813 char tmpString[64];
814
815 if (strncmp(line, "Filesystem", 10) == 0)
816 continue;
817 if (strlen(line) < min_len) {
818 include_block = 0;
819 continue;
820 }
821 if (include_block) {
822 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
823 } else {
824 // The device block string is so long that the df information is on the next line
825 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -0400826 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400827 while (tmpString[space_count] == 32)
828 space_count++;
829 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
830 }
831
832 // Adjust block size to byte size
833 Size = blocks * 1024ULL;
834 Used = used * 1024ULL;
835 Free = available * 1024ULL;
836 Backup_Size = Used;
837 }
838 fclose(fp);
839 return true;
840}
841
Dees_Troy5bf43922012-09-07 16:07:55 -0400842bool TWPartition::Find_Partition_Size(void) {
843 FILE* fp;
844 char line[512];
845 string tmpdevice;
846
igoriok87e3d932013-01-31 21:03:53 +0200847 fp = fopen("/proc/dumchar_info", "rt");
848 if (fp != NULL) {
849 while (fgets(line, sizeof(line), fp) != NULL)
850 {
851 char label[32], device[32];
852 unsigned long size = 0;
853
854 sscanf(line, "%s %lx %*lx %*lu %s", label, &size, device);
855
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500856 // Skip header, annotation and blank lines
igoriok87e3d932013-01-31 21:03:53 +0200857 if ((strncmp(device, "/dev/", 5) != 0) || (strlen(line) < 8))
858 continue;
859
860 tmpdevice = "/dev/";
861 tmpdevice += label;
862 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
863 Size = size;
864 fclose(fp);
865 return true;
866 }
867 }
868 }
869
Dees_Troy5bf43922012-09-07 16:07:55 -0400870 // In this case, we'll first get the partitions we care about (with labels)
871 fp = fopen("/proc/partitions", "rt");
872 if (fp == NULL)
873 return false;
874
875 while (fgets(line, sizeof(line), fp) != NULL)
876 {
877 unsigned long major, minor, blocks;
878 char device[512];
879 char tmpString[64];
880
Dees_Troy63c8df72012-09-10 14:02:05 -0400881 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400882 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
883
884 tmpdevice = "/dev/block/";
885 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -0400886 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400887 // Adjust block size to byte size
888 Size = blocks * 1024ULL;
889 fclose(fp);
890 return true;
891 }
892 }
893 fclose(fp);
894 return false;
895}
896
Dees_Troy5bf43922012-09-07 16:07:55 -0400897bool TWPartition::Is_Mounted(void) {
898 if (!Can_Be_Mounted)
899 return false;
900
901 struct stat st1, st2;
902 string test_path;
903
904 // Check to see if the mount point directory exists
905 test_path = Mount_Point + "/.";
906 if (stat(test_path.c_str(), &st1) != 0) return false;
907
908 // Check to see if the directory above the mount point exists
909 test_path = Mount_Point + "/../.";
910 if (stat(test_path.c_str(), &st2) != 0) return false;
911
912 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
913 int ret = (st1.st_dev != st2.st_dev) ? true : false;
914
915 return ret;
916}
917
918bool TWPartition::Mount(bool Display_Error) {
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000919 int exfat_mounted = 0;
920
Dees_Troy5bf43922012-09-07 16:07:55 -0400921 if (Is_Mounted()) {
922 return true;
923 } else if (!Can_Be_Mounted) {
924 return false;
925 }
Dees_Troy38bd7602012-09-14 13:33:53 -0400926
927 Find_Actual_Block_Device();
928
929 // Check the current file system before mounting
930 Check_FS_Type();
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000931 if (Current_File_System == "exfat" && TWFunc::Path_Exists("/sbin/exfat-fuse")) {
Dees_Troye34c1332013-02-06 19:13:00 +0000932 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 +0000933 LOGINFO("cmd: %s\n", cmd.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000934 string result;
935 if (TWFunc::Exec_Cmd(cmd, result) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000936 LOGINFO("exfat-fuse failed to mount with result '%s', trying vfat\n", result.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000937 Current_File_System = "vfat";
938 } else {
939#ifdef TW_NO_EXFAT_FUSE
940 UnMount(false);
941 // We'll let the kernel handle it but using exfat-fuse to detect if the file system is actually exfat
942 // Some kernels let us mount vfat as exfat which doesn't work out too well
943#else
944 exfat_mounted = 1;
945#endif
946 }
947 }
Dees_Troy22042032012-12-18 21:23:08 +0000948 if (Fstab_File_System == "yaffs2") {
949 // mount an MTD partition as a YAFFS2 filesystem.
Dees_Troy76543db2013-06-19 16:24:30 +0000950 const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
951 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags, NULL) < 0) {
952 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Fstab_File_System.c_str(), flags | MS_RDONLY, NULL) < 0) {
953 if (Display_Error)
954 LOGERR("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
955 else
956 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
957 return false;
958 } else {
959 LOGINFO("Mounted '%s' (MTD) as RO\n", Mount_Point.c_str());
960 return true;
961 }
962 } else {
963 struct stat st;
964 string test_path = Mount_Point;
965 if (stat(test_path.c_str(), &st) < 0) {
966 if (Display_Error)
967 LOGERR("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
968 else
969 LOGINFO("Failed to mount '%s' (MTD)\n", Mount_Point.c_str());
970 return false;
971 }
972 mode_t new_mode = st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
973 if (new_mode != st.st_mode) {
974 LOGINFO("Fixing execute permissions for %s\n", Mount_Point.c_str());
975 if (chmod(Mount_Point.c_str(), new_mode) < 0) {
976 if (Display_Error)
977 LOGERR("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
978 else
979 LOGINFO("Couldn't fix permissions for %s: %s\n", Mount_Point.c_str(), strerror(errno));
980 return false;
981 }
982 }
Dees_Troy22042032012-12-18 21:23:08 +0000983 return true;
Dees_Troy76543db2013-06-19 16:24:30 +0000984 }
Dees Troy216e0422014-02-07 03:46:42 +0000985 } 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 +0000986#ifdef TW_NO_EXFAT_FUSE
987 if (Current_File_System == "exfat") {
Dees_Troy2673cec2013-04-02 20:22:16 +0000988 LOGINFO("Mounting exfat failed, trying vfat...\n");
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000989 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), "vfat", 0, NULL) != 0) {
Dees_Troy85f44ed2013-01-09 18:42:36 +0000990 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000991 LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
Dees_Troy85f44ed2013-01-09 18:42:36 +0000992 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000993 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
Hashcode62bd9e02013-11-19 21:59:42 -0800994 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 +0000995 return false;
Dees_Troy85f44ed2013-01-09 18:42:36 +0000996 }
Dees_Troyb05ddee2013-01-28 20:24:50 +0000997 } else {
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000998#endif
999 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001000 LOGERR("Unable to mount '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001001 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001002 LOGINFO("Unable to mount '%s'\n", Mount_Point.c_str());
1003 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 +00001004 return false;
1005#ifdef TW_NO_EXFAT_FUSE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001006 }
1007#endif
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001008 }
1009#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1010 string MetaEcfsFile = EXPAND(TW_EXTERNAL_STORAGE_PATH);
1011 MetaEcfsFile += "/.MetaEcfsFile";
1012 if (EcryptFS_Password.size() > 0 && PartitionManager.Mount_By_Path("/data", false) && TWFunc::Path_Exists(MetaEcfsFile)) {
1013 if (mount_ecryptfs_drive(EcryptFS_Password.c_str(), Mount_Point.c_str(), Mount_Point.c_str(), 0) != 0) {
1014 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001015 LOGERR("Unable to mount ecryptfs for '%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 ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001018 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001019 LOGINFO("Successfully mounted ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001020 Is_Decrypted = true;
Dees_Troy51127312012-09-08 13:08:49 -04001021 }
Dees_Troy066eb302013-08-23 17:20:32 +00001022 } else if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
1023 if (Is_Decrypted)
1024 LOGINFO("Mounting external storage, '%s' is not encrypted\n", Mount_Point.c_str());
Dees_Troy3f5c4e82013-02-01 15:16:59 +00001025 Is_Decrypted = false;
1026 }
1027#endif
1028 if (Removable)
1029 Update_Size(Display_Error);
1030
1031 if (!Symlink_Mount_Point.empty()) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001032 string Command = "mount '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
1033 TWFunc::Exec_Cmd(Command);
Dees_Troy5bf43922012-09-07 16:07:55 -04001034 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001035 return true;
1036}
1037
1038bool TWPartition::UnMount(bool Display_Error) {
1039 if (Is_Mounted()) {
1040 int never_unmount_system;
1041
1042 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
1043 if (never_unmount_system == 1 && Mount_Point == "/system")
1044 return true; // Never unmount system if you're not supposed to unmount it
1045
Dees_Troyc8bafa12013-01-10 15:43:00 +00001046#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1047 if (EcryptFS_Password.size() > 0) {
1048 if (unmount_ecryptfs_drive(Mount_Point.c_str()) != 0) {
1049 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001050 LOGERR("Unable to unmount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001051 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001052 LOGINFO("Unable to unmount ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001053 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001054 LOGINFO("Successfully unmounted ecryptfs for '%s'\n", Mount_Point.c_str());
Dees_Troyc8bafa12013-01-10 15:43:00 +00001055 }
1056 }
1057#endif
1058
Dees_Troy38bd7602012-09-14 13:33:53 -04001059 if (!Symlink_Mount_Point.empty())
1060 umount(Symlink_Mount_Point.c_str());
1061
Dees_Troyb05ddee2013-01-28 20:24:50 +00001062 umount(Mount_Point.c_str());
1063 if (Is_Mounted()) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001064 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +00001065 LOGERR("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001066 else
Dees_Troy2673cec2013-04-02 20:22:16 +00001067 LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -04001068 return false;
1069 } else
1070 return true;
1071 } else {
1072 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001073 }
1074}
1075
Gary Peck43acadf2012-11-21 21:19:01 -08001076bool TWPartition::Wipe(string New_File_System) {
Dees_Troy16c2b312013-01-15 16:51:18 +00001077 bool wiped = false, update_crypt = false;
1078 int check;
1079 string Layout_Filename = Mount_Point + "/.layout_version";
1080
Dees_Troy38bd7602012-09-14 13:33:53 -04001081 if (!Can_Be_Wiped) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001082 LOGERR("Partition '%s' cannot be wiped.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001083 return false;
1084 }
1085
Dees_Troyc51f1f92012-09-20 15:32:13 -04001086 if (Mount_Point == "/cache")
Dees_Troy2673cec2013-04-02 20:22:16 +00001087 Log_Offset = 0;
Dees_Troyc51f1f92012-09-20 15:32:13 -04001088
Dees_Troyce675462013-01-09 19:48:21 +00001089#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1090 if (Mount_Point == "/data" && Mount(false)) {
1091 if (TWFunc::Path_Exists("/data/system/edk_p_sd"))
1092 TWFunc::copy_file("/data/system/edk_p_sd", "/tmp/edk_p_sd", 0600);
1093 }
1094#endif
1095
Dees_Troy16c2b312013-01-15 16:51:18 +00001096 if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
1097 TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
1098 else
1099 unlink("/.layout_version");
Dees_Troy38bd7602012-09-14 13:33:53 -04001100
Dees_Troy16c2b312013-01-15 16:51:18 +00001101 if (Has_Data_Media) {
1102 wiped = Wipe_Data_Without_Wiping_Media();
1103 } else {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001104
Dees_Troy16c2b312013-01-15 16:51:18 +00001105 DataManager::GetValue(TW_RM_RF_VAR, check);
1106
Hashcodedabfd492013-08-29 22:45:30 -07001107 if (check || Use_Rm_Rf)
Dees_Troy16c2b312013-01-15 16:51:18 +00001108 wiped = Wipe_RMRF();
1109 else if (New_File_System == "ext4")
1110 wiped = Wipe_EXT4();
1111 else if (New_File_System == "ext2" || New_File_System == "ext3")
1112 wiped = Wipe_EXT23(New_File_System);
1113 else if (New_File_System == "vfat")
1114 wiped = Wipe_FAT();
1115 else if (New_File_System == "exfat")
1116 wiped = Wipe_EXFAT();
1117 else if (New_File_System == "yaffs2")
1118 wiped = Wipe_MTD();
Dees_Troye5017042013-08-29 16:38:55 +00001119 else if (New_File_System == "f2fs")
1120 wiped = Wipe_F2FS();
Dees_Troy16c2b312013-01-15 16:51:18 +00001121 else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001122 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 +00001123 unlink("/.layout_version");
1124 return false;
1125 }
1126 update_crypt = wiped;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001127 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001128
Gary Pecke8bc5d72012-12-21 06:45:25 -08001129 if (wiped) {
Dees_Troyce675462013-01-09 19:48:21 +00001130#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
1131 if (Mount_Point == "/data" && Mount(false)) {
1132 if (TWFunc::Path_Exists("/tmp/edk_p_sd")) {
1133 Make_Dir("/data/system", true);
1134 TWFunc::copy_file("/tmp/edk_p_sd", "/data/system/edk_p_sd", 0600);
1135 }
1136 }
1137#endif
Dees_Troy16c2b312013-01-15 16:51:18 +00001138
Dees_Troy1c1ac442013-01-17 21:42:14 +00001139 if (Mount_Point == "/cache")
1140 DataManager::Output_Version();
1141
Dees_Troy16c2b312013-01-15 16:51:18 +00001142 if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
1143 TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
1144
1145 if (update_crypt) {
1146 Setup_File_System(false);
1147 if (Is_Encrypted && !Is_Decrypted) {
1148 // just wiped an encrypted partition back to its unencrypted state
1149 Is_Encrypted = false;
1150 Is_Decrypted = false;
1151 Decrypted_Block_Device = "";
1152 if (Mount_Point == "/data") {
1153 DataManager::SetValue(TW_IS_ENCRYPTED, 0);
1154 DataManager::SetValue(TW_IS_DECRYPTED, 0);
1155 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001156 }
1157 }
1158 }
1159 return wiped;
Dees_Troy51a0e822012-09-05 15:24:24 -04001160}
1161
Gary Peck43acadf2012-11-21 21:19:01 -08001162bool TWPartition::Wipe() {
Gary Peck82599a82012-11-21 16:23:12 -08001163 if (Is_File_System(Current_File_System))
1164 return Wipe(Current_File_System);
1165 else
1166 return Wipe(Fstab_File_System);
Gary Peck43acadf2012-11-21 21:19:01 -08001167}
1168
Dees_Troye58d5262012-09-21 12:27:57 -04001169bool TWPartition::Wipe_AndSec(void) {
1170 if (!Has_Android_Secure)
1171 return false;
1172
Dees_Troye58d5262012-09-21 12:27:57 -04001173 if (!Mount(true))
1174 return false;
1175
Dees_Troy2673cec2013-04-02 20:22:16 +00001176 gui_print("Wiping %s\n", Backup_Display_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001177 TWFunc::removeDir(Mount_Point + "/.android_secure/", true);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001178 return true;
Dees_Troye58d5262012-09-21 12:27:57 -04001179}
1180
Dees_Troy51a0e822012-09-05 15:24:24 -04001181bool TWPartition::Backup(string backup_folder) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001182 if (Backup_Method == FILES)
1183 return Backup_Tar(backup_folder);
1184 else if (Backup_Method == DD)
1185 return Backup_DD(backup_folder);
1186 else if (Backup_Method == FLASH_UTILS)
1187 return Backup_Dump_Image(backup_folder);
Dees_Troy2673cec2013-04-02 20:22:16 +00001188 LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001189 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001190}
1191
Dees_Troy43d8b002012-09-17 16:00:01 -04001192bool TWPartition::Check_MD5(string restore_folder) {
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001193 string Full_Filename, md5file;
Dees_Troy43d8b002012-09-17 16:00:01 -04001194 char split_filename[512];
1195 int index = 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001196 twrpDigest md5sum;
Dees_Troy43d8b002012-09-17 16:00:01 -04001197
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001198 memset(split_filename, 0, sizeof(split_filename));
Dees_Troy43d8b002012-09-17 16:00:01 -04001199 Full_Filename = restore_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04001200 if (!TWFunc::Path_Exists(Full_Filename)) {
1201 // This is a split archive, we presume
1202 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
Dees_Troy2673cec2013-04-02 20:22:16 +00001203 LOGINFO("split_filename: %s\n", split_filename);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001204 md5file = split_filename;
1205 md5file += ".md5";
1206 if (!TWFunc::Path_Exists(md5file)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001207 LOGERR("No md5 file found for '%s'.\n", split_filename);
1208 LOGERR("Please unselect Enable MD5 verification to restore.\n");
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001209 return false;
1210 }
1211 md5sum.setfn(split_filename);
Dees_Troy83bd4832013-05-04 12:39:56 +00001212 while (index < 1000) {
1213 if (TWFunc::Path_Exists(split_filename) && md5sum.verify_md5digest() != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001214 LOGERR("MD5 failed to match on '%s'.\n", split_filename);
Dees_Troy43d8b002012-09-17 16:00:01 -04001215 return false;
1216 }
1217 index++;
1218 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001219 md5sum.setfn(split_filename);
Dees_Troy43d8b002012-09-17 16:00:01 -04001220 }
Dees_Troy4a2a1262012-09-18 09:33:47 -04001221 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -04001222 } else {
1223 // Single file archive
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001224 md5file = Full_Filename + ".md5";
1225 if (!TWFunc::Path_Exists(md5file)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001226 LOGERR("No md5 file found for '%s'.\n", Full_Filename.c_str());
1227 LOGERR("Please unselect Enable MD5 verification to restore.\n");
bigbiff bigbiff65a4c732013-03-15 15:17:50 -04001228 return false;
1229 }
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001230 md5sum.setfn(Full_Filename);
1231 if (md5sum.verify_md5digest() != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001232 LOGERR("MD5 failed to match on '%s'.\n", Full_Filename.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001233 return false;
1234 } else
1235 return true;
1236 }
1237 return false;
1238}
1239
Dees_Troy51a0e822012-09-05 15:24:24 -04001240bool TWPartition::Restore(string restore_folder) {
Gary Peck43acadf2012-11-21 21:19:01 -08001241 size_t first_period, second_period;
1242 string Restore_File_System;
1243
1244 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy2673cec2013-04-02 20:22:16 +00001245 LOGINFO("Restore filename is: %s\n", Backup_FileName.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001246
1247 // Parse backup filename to extract the file system before wiping
1248 first_period = Backup_FileName.find(".");
1249 if (first_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001250 LOGERR("Unable to find file system (first period).\n");
Gary Peck43acadf2012-11-21 21:19:01 -08001251 return false;
1252 }
1253 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
1254 second_period = Restore_File_System.find(".");
1255 if (second_period == string::npos) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001256 LOGERR("Unable to find file system (second period).\n");
Gary Peck43acadf2012-11-21 21:19:01 -08001257 return false;
1258 }
1259 Restore_File_System.resize(second_period);
Dees_Troy2673cec2013-04-02 20:22:16 +00001260 LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001261
1262 if (Is_File_System(Restore_File_System))
1263 return Restore_Tar(restore_folder, Restore_File_System);
1264 else if (Is_Image(Restore_File_System)) {
1265 if (Restore_File_System == "emmc")
1266 return Restore_DD(restore_folder);
1267 else if (Restore_File_System == "mtd" || Restore_File_System == "bml")
1268 return Restore_Flash_Image(restore_folder);
1269 }
1270
Dees_Troy2673cec2013-04-02 20:22:16 +00001271 LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001272 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001273}
1274
1275string TWPartition::Backup_Method_By_Name() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001276 if (Backup_Method == NONE)
1277 return "none";
1278 else if (Backup_Method == FILES)
1279 return "files";
1280 else if (Backup_Method == DD)
1281 return "dd";
1282 else if (Backup_Method == FLASH_UTILS)
1283 return "flash_utils";
1284 else
1285 return "undefined";
1286 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -04001287}
1288
1289bool TWPartition::Decrypt(string Password) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001290 LOGINFO("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001291 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -04001292 return 1;
1293}
1294
1295bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001296 bool Save_Data_Media = Has_Data_Media;
1297
1298 if (!UnMount(true))
1299 return false;
1300
Dees_Troy38bd7602012-09-14 13:33:53 -04001301 Has_Data_Media = false;
Dees_Troy74fb2e92013-04-15 14:35:47 +00001302 Decrypted_Block_Device = "";
1303 Is_Decrypted = false;
1304 Is_Encrypted = false;
Gary Pecke8bc5d72012-12-21 06:45:25 -08001305 if (Wipe(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001306 Has_Data_Media = Save_Data_Media;
1307 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
1308 Recreate_Media_Folder();
1309 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001310 gui_print("You may need to reboot recovery to be able to use /data again.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001311 return true;
1312 } else {
1313 Has_Data_Media = Save_Data_Media;
Dees_Troy2673cec2013-04-02 20:22:16 +00001314 LOGERR("Unable to format to remove encryption.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001315 return false;
1316 }
1317 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001318}
1319
1320void TWPartition::Check_FS_Type() {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001321 const char* type;
1322 blkid_probe pr;
Dees_Troy5bf43922012-09-07 16:07:55 -04001323
Dees_Troy68cab492012-12-12 19:29:35 +00001324 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd" || Fstab_File_System == "bml" || Ignore_Blkid)
1325 return; // Running blkid on some mtd devices causes a massive crash or needs to be skipped
Dees_Troy5bf43922012-09-07 16:07:55 -04001326
Dees_Troy38bd7602012-09-14 13:33:53 -04001327 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -04001328 if (!Is_Present)
1329 return;
Dees_Troy51127312012-09-08 13:08:49 -04001330
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001331 pr = blkid_new_probe_from_filename(Actual_Block_Device.c_str());
1332 if (blkid_do_fullprobe(pr)) {
1333 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001334 LOGINFO("Can't probe device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001335 return;
Dees_Troy5bf43922012-09-07 16:07:55 -04001336 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001337
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001338 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0) {
1339 blkid_free_probe(pr);
Dees_Troy2673cec2013-04-02 20:22:16 +00001340 LOGINFO("can't find filesystem on device %s\n", Actual_Block_Device.c_str());
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001341 return;
1342 }
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001343
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001344 Current_File_System = type;
Vojtech Bocek4d4b3362013-06-24 22:46:13 +02001345 blkid_free_probe(pr);
Dees_Troy51a0e822012-09-05 15:24:24 -04001346}
1347
Gary Peck43acadf2012-11-21 21:19:01 -08001348bool TWPartition::Wipe_EXT23(string File_System) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001349 if (!UnMount(true))
1350 return false;
1351
Dees_Troy43d8b002012-09-17 16:00:01 -04001352 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001353 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001354
Dees_Troy2673cec2013-04-02 20:22:16 +00001355 gui_print("Formatting %s using mke2fs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001356 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001357 command = "mke2fs -t " + File_System + " -m 0 " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001358 LOGINFO("mke2fs command: %s\n", command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001359 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001360 Current_File_System = File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04001361 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001362 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001363 return true;
1364 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001365 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001366 return false;
1367 }
1368 } else
1369 return Wipe_RMRF();
1370
1371 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001372}
1373
1374bool TWPartition::Wipe_EXT4() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001375 if (!UnMount(true))
1376 return false;
1377
Dees_Troyb3265ab2013-08-30 02:59:14 +00001378#if defined(HAVE_SELINUX) && defined(USE_EXT4)
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001379 int ret;
1380 char *secontext = NULL;
1381
Dees_Troya95f55c2013-08-17 13:14:43 +00001382 gui_print("Formatting %s using make_ext4fs function.\n", Display_Name.c_str());
Ethan Yonkerf27497f2014-02-09 11:48:33 -06001383
1384 if (selabel_lookup(selinux_handle, &secontext, Mount_Point.c_str(), S_IFDIR) < 0) {
1385 LOGINFO("Cannot lookup security context for '%s'\n", Mount_Point.c_str());
1386 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), NULL);
1387 } else {
1388 ret = make_ext4fs(Actual_Block_Device.c_str(), Length, Mount_Point.c_str(), selinux_handle);
1389 }
1390 if (ret != 0) {
Dees_Troya95f55c2013-08-17 13:14:43 +00001391 LOGERR("Unable to wipe '%s' using function call.\n", Mount_Point.c_str());
1392 return false;
1393 } else {
bigbiff bigbiffc49d7062013-10-11 20:28:00 -04001394 string sedir = Mount_Point + "/lost+found";
1395 PartitionManager.Mount_By_Path(sedir.c_str(), true);
1396 rmdir(sedir.c_str());
1397 mkdir(sedir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP);
Dees_Troya95f55c2013-08-17 13:14:43 +00001398 return true;
1399 }
1400#else
Dees_Troy43d8b002012-09-17 16:00:01 -04001401 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001402 string Command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001403
Dees_Troy2673cec2013-04-02 20:22:16 +00001404 gui_print("Formatting %s using make_ext4fs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001405 Find_Actual_Block_Device();
1406 Command = "make_ext4fs";
1407 if (!Is_Decrypted && Length != 0) {
1408 // Only use length if we're not decrypted
1409 char len[32];
1410 sprintf(len, "%i", Length);
1411 Command += " -l ";
1412 Command += len;
1413 }
Dees_Troy5295d582013-09-06 15:51:08 +00001414 if (TWFunc::Path_Exists("/file_contexts")) {
1415 Command += " -S /file_contexts";
1416 }
1417 Command += " -a " + Mount_Point + " " + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001418 LOGINFO("make_ext4fs command: %s\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001419 if (TWFunc::Exec_Cmd(Command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001420 Current_File_System = "ext4";
Dees_Troye58d5262012-09-21 12:27:57 -04001421 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001422 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001423 return true;
1424 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001425 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001426 return false;
1427 }
1428 } else
Gary Peck43acadf2012-11-21 21:19:01 -08001429 return Wipe_EXT23("ext4");
Dees_Troya95f55c2013-08-17 13:14:43 +00001430#endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001431 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001432}
1433
1434bool TWPartition::Wipe_FAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001435 string command;
Dees_Troy38bd7602012-09-14 13:33:53 -04001436
Dees_Troy43d8b002012-09-17 16:00:01 -04001437 if (TWFunc::Path_Exists("/sbin/mkdosfs")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001438 if (!UnMount(true))
1439 return false;
1440
Dees_Troy2673cec2013-04-02 20:22:16 +00001441 gui_print("Formatting %s using mkdosfs...\n", Display_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001442 Find_Actual_Block_Device();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001443 command = "mkdosfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001444 if (TWFunc::Exec_Cmd(command) == 0) {
Gary Pecke8bc5d72012-12-21 06:45:25 -08001445 Current_File_System = "vfat";
Dees_Troye58d5262012-09-21 12:27:57 -04001446 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001447 gui_print("Done.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001448 return true;
1449 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001450 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001451 return false;
1452 }
1453 return true;
1454 }
1455 else
1456 return Wipe_RMRF();
1457
1458 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001459}
1460
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001461bool TWPartition::Wipe_EXFAT() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001462 string command;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001463
1464 if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
1465 if (!UnMount(true))
1466 return false;
1467
Dees_Troy2673cec2013-04-02 20:22:16 +00001468 gui_print("Formatting %s using mkexfatfs...\n", Display_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001469 Find_Actual_Block_Device();
1470 command = "mkexfatfs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001471 if (TWFunc::Exec_Cmd(command) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001472 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001473 gui_print("Done.\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001474 return true;
1475 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001476 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001477 return false;
1478 }
1479 return true;
1480 }
1481 return false;
1482}
1483
Dees_Troy38bd7602012-09-14 13:33:53 -04001484bool TWPartition::Wipe_MTD() {
1485 if (!UnMount(true))
1486 return false;
1487
Dees_Troy2673cec2013-04-02 20:22:16 +00001488 gui_print("MTD Formatting \"%s\"\n", MTD_Name.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001489
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001490 mtd_scan_partitions();
1491 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
1492 if (mtd == NULL) {
1493 LOGERR("No mtd partition named '%s'", MTD_Name.c_str());
1494 return false;
1495 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001496
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001497 MtdWriteContext* ctx = mtd_write_partition(mtd);
1498 if (ctx == NULL) {
1499 LOGERR("Can't write '%s', failed to format.", MTD_Name.c_str());
1500 return false;
1501 }
1502 if (mtd_erase_blocks(ctx, -1) == -1) {
1503 mtd_write_close(ctx);
1504 LOGERR("Failed to format '%s'", MTD_Name.c_str());
1505 return false;
1506 }
1507 if (mtd_write_close(ctx) != 0) {
1508 LOGERR("Failed to close '%s'", MTD_Name.c_str());
1509 return false;
1510 }
Gary Pecke8bc5d72012-12-21 06:45:25 -08001511 Current_File_System = "yaffs2";
Dees_Troye58d5262012-09-21 12:27:57 -04001512 Recreate_AndSec_Folder();
Dees_Troy2673cec2013-04-02 20:22:16 +00001513 gui_print("Done.\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001514 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001515}
1516
1517bool TWPartition::Wipe_RMRF() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001518 if (!Mount(true))
1519 return false;
1520
Dees_Troy2673cec2013-04-02 20:22:16 +00001521 gui_print("Removing all files under '%s'\n", Mount_Point.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001522 TWFunc::removeDir(Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04001523 Recreate_AndSec_Folder();
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001524 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001525}
1526
Dees_Troye5017042013-08-29 16:38:55 +00001527bool TWPartition::Wipe_F2FS() {
Vojtech Bocek05534202013-09-11 08:11:56 +02001528 string command;
Dees_Troye5017042013-08-29 16:38:55 +00001529
1530 if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
1531 if (!UnMount(true))
1532 return false;
1533
1534 gui_print("Formatting %s using mkfs.f2fs...\n", Display_Name.c_str());
1535 Find_Actual_Block_Device();
1536 command = "mkfs.f2fs " + Actual_Block_Device;
Vojtech Bocek05534202013-09-11 08:11:56 +02001537 if (TWFunc::Exec_Cmd(command) == 0) {
Dees_Troye5017042013-08-29 16:38:55 +00001538 Recreate_AndSec_Folder();
1539 gui_print("Done.\n");
1540 return true;
1541 } else {
1542 LOGERR("Unable to wipe '%s'.\n", Mount_Point.c_str());
1543 return false;
1544 }
1545 return true;
1546 } else {
1547 gui_print("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
1548 return Wipe_RMRF();
1549 }
1550 return false;
1551}
1552
Dees_Troy51a0e822012-09-05 15:24:24 -04001553bool TWPartition::Wipe_Data_Without_Wiping_Media() {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001554 string dir;
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001555 #ifdef HAVE_SELINUX
1556 fixPermissions perms;
1557 #endif
Dees_Troy38bd7602012-09-14 13:33:53 -04001558
1559 // This handles wiping data on devices with "sdcard" in /data/media
1560 if (!Mount(true))
1561 return false;
1562
Dees_Troy2673cec2013-04-02 20:22:16 +00001563 gui_print("Wiping data without wiping /data/media ...\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001564
1565 DIR* d;
1566 d = opendir("/data");
Dees_Troy16b74352012-11-14 22:27:31 +00001567 if (d != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001568 struct dirent* de;
1569 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001570 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
Dees_Troy16b74352012-11-14 22:27:31 +00001571 // The media folder is the "internal sdcard"
1572 // The .layout_version file is responsible for determining whether 4.2 decides up upgrade
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001573 // the media folder for multi-user.
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001574 //TODO: convert this to use twrpDU.cpp
Dees_Troy16b74352012-11-14 22:27:31 +00001575 if (strcmp(de->d_name, "media") == 0 || strcmp(de->d_name, ".layout_version") == 0) continue;
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001576
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001577 dir = "/data/";
1578 dir.append(de->d_name);
Dees_Troyce675462013-01-09 19:48:21 +00001579 if (de->d_type == DT_DIR) {
1580 TWFunc::removeDir(dir, false);
bigbiff bigbiff98f1f902013-01-19 18:46:13 -05001581 } 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 +00001582 if (!unlink(dir.c_str()))
Dees_Troy2673cec2013-04-02 20:22:16 +00001583 LOGINFO("Unable to unlink '%s'\n", dir.c_str());
Dees_Troyce675462013-01-09 19:48:21 +00001584 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001585 }
1586 closedir(d);
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001587
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001588 #ifdef HAVE_SELINUX
1589 perms.fixDataInternalContexts();
1590 #endif
1591
Dees_Troy2673cec2013-04-02 20:22:16 +00001592 gui_print("Done.\n");
Dees_Troy16b74352012-11-14 22:27:31 +00001593 return true;
Dees_Troy38bd7602012-09-14 13:33:53 -04001594 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001595 gui_print("Dirent failed to open /data, error!\n");
Dees_Troy16b74352012-11-14 22:27:31 +00001596 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001597}
1598
1599bool TWPartition::Backup_Tar(string backup_folder) {
Dees_Troy4a2a1262012-09-18 09:33:47 -04001600 char back_name[255], split_index[5];
1601 string Full_FileName, Split_FileName, Tar_Args, Command;
Dees_Troy83bd4832013-05-04 12:39:56 +00001602 int use_compression, use_encryption = 0, index, backup_count;
Dees_Troy4a2a1262012-09-18 09:33:47 -04001603 struct stat st;
Dees_Troy7c2dec82012-09-26 09:49:14 -04001604 unsigned long long total_bsize = 0, file_size;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001605 twrpTar tar;
1606 vector <string> files;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -05001607
Dees_Troy43d8b002012-09-17 16:00:01 -04001608 if (!Mount(true))
1609 return false;
1610
Dees_Troya13d74f2013-03-24 08:54:55 -05001611 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001612 gui_print("Backing up %s...\n", Backup_Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001613
1614 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
Dees_Troy83bd4832013-05-04 12:39:56 +00001615 tar.use_compression = use_compression;
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001616 //exclude Google Music Cache
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001617 vector<string> excludedirs = du.get_absolute_dirs();
1618 for (int i = 0; i < excludedirs.size(); ++i) {
1619 tar.setexcl(excludedirs.at(i));
1620 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001621#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
1622 DataManager::GetValue("tw_encrypt_backup", use_encryption);
1623 if (use_encryption && Can_Encrypt_Backup) {
1624 tar.use_encryption = use_encryption;
1625 if (Use_Userdata_Encryption)
1626 tar.userdata_encryption = use_encryption;
Ethan Yonker87af5632014-02-10 11:56:35 -06001627 string Password;
1628 DataManager::GetValue("tw_backup_password", Password);
1629 tar.setpassword(Password);
Dees_Troy83bd4832013-05-04 12:39:56 +00001630 } else {
1631 use_encryption = false;
1632 }
1633#endif
Dees_Troy43d8b002012-09-17 16:00:01 -04001634
1635 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1636 Backup_FileName = back_name;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001637 Full_FileName = backup_folder + "/" + Backup_FileName;
Dees_Troy83bd4832013-05-04 12:39:56 +00001638 tar.has_data_media = Has_Data_Media;
Dees Troye0a433a2013-12-02 04:10:37 +00001639 Full_FileName = backup_folder + "/" + Backup_FileName;
1640 tar.setdir(Backup_Path);
1641 tar.setfn(Full_FileName);
1642 tar.setsize(Backup_Size);
1643 if (tar.createTarFork() != 0)
1644 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04001645 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001646}
1647
1648bool TWPartition::Backup_DD(string backup_folder) {
igoriok87e3d932013-01-31 21:03:53 +02001649 char back_name[255], backup_size[32];
Vojtech Bocek05534202013-09-11 08:11:56 +02001650 string Full_FileName, Command, DD_BS;
Dees_Troy43d8b002012-09-17 16:00:01 -04001651 int use_compression;
1652
igoriok87e3d932013-01-31 21:03:53 +02001653 sprintf(backup_size, "%llu", Backup_Size);
1654 DD_BS = backup_size;
1655
Dees_Troyb46a6842012-09-25 11:06:46 -04001656 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001657 gui_print("Backing up %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001658
1659 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1660 Backup_FileName = back_name;
1661
1662 Full_FileName = backup_folder + "/" + Backup_FileName;
1663
igoriok87e3d932013-01-31 21:03:53 +02001664 Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'" + " bs=" + DD_BS + "c count=1";
Dees_Troy2673cec2013-04-02 20:22:16 +00001665 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001666 TWFunc::Exec_Cmd(Command);
Dees_Troyc154ac22012-10-12 15:36:47 -04001667 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001668 LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04001669 return false;
1670 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001671 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001672}
1673
1674bool TWPartition::Backup_Dump_Image(string backup_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001675 char back_name[255];
Vojtech Bocek05534202013-09-11 08:11:56 +02001676 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04001677 int use_compression;
1678
Dees_Troyb46a6842012-09-25 11:06:46 -04001679 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy2673cec2013-04-02 20:22:16 +00001680 gui_print("Backing up %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001681
1682 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1683 Backup_FileName = back_name;
1684
1685 Full_FileName = backup_folder + "/" + Backup_FileName;
1686
1687 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
Dees_Troy2673cec2013-04-02 20:22:16 +00001688 LOGINFO("Backup command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001689 TWFunc::Exec_Cmd(Command);
Dees_Troy7c2dec82012-09-26 09:49:14 -04001690 if (TWFunc::Get_File_Size(Full_FileName) == 0) {
1691 // 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 +00001692 LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
Dees_Troy7c2dec82012-09-26 09:49:14 -04001693 return false;
1694 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001695 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001696}
1697
Gary Peck43acadf2012-11-21 21:19:01 -08001698bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System) {
1699 string Full_FileName, Command;
Dees_Troy4a2a1262012-09-18 09:33:47 -04001700 int index = 0;
1701 char split_index[5];
Dees_Troy43d8b002012-09-17 16:00:01 -04001702
Dees_Troye58d5262012-09-21 12:27:57 -04001703 if (Has_Android_Secure) {
Dees_Troye58d5262012-09-21 12:27:57 -04001704 if (!Wipe_AndSec())
1705 return false;
Gary Peck43acadf2012-11-21 21:19:01 -08001706 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001707 gui_print("Wiping %s...\n", Display_Name.c_str());
Gary Peck43acadf2012-11-21 21:19:01 -08001708 if (!Wipe(Restore_File_System))
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001709 return false;
Dees_Troye58d5262012-09-21 12:27:57 -04001710 }
Dees_Troya13d74f2013-03-24 08:54:55 -05001711 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, "Restoring");
Dees_Troy2673cec2013-04-02 20:22:16 +00001712 gui_print("Restoring %s...\n", Backup_Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001713
1714 if (!Mount(true))
1715 return false;
1716
Dees_Troy4a2a1262012-09-18 09:33:47 -04001717 Full_FileName = restore_folder + "/" + Backup_FileName;
Ethan Yonker87af5632014-02-10 11:56:35 -06001718 twrpTar tar;
1719 tar.setdir(Backup_Path);
1720 tar.setfn(Full_FileName);
1721 tar.backup_name = Backup_Name;
1722#ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS
1723 string Password;
1724 DataManager::GetValue("tw_restore_password", Password);
1725 if (!Password.empty())
1726 tar.setpassword(Password);
1727#endif
1728 if (tar.extractTarFork() != 0)
1729 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04001730 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001731}
1732
1733bool TWPartition::Restore_DD(string restore_folder) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001734 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04001735
Dees_Troyda8b55a2012-12-12 19:18:30 +00001736 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy43d8b002012-09-17 16:00:01 -04001737 Full_FileName = restore_folder + "/" + Backup_FileName;
Gary Peck15e623d2012-11-21 21:07:58 -08001738
1739 if (!Find_Partition_Size()) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001740 LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str());
Gary Peck15e623d2012-11-21 21:07:58 -08001741 return false;
1742 }
1743 unsigned long long backup_size = TWFunc::Get_File_Size(Full_FileName);
1744 if (backup_size > Size) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001745 LOGERR("Size (%iMB) of backup '%s' is larger than target device '%s' (%iMB)\n",
Gary Peck15e623d2012-11-21 21:07:58 -08001746 (int)(backup_size / 1048576LLU), Full_FileName.c_str(),
1747 Actual_Block_Device.c_str(), (int)(Size / 1048576LLU));
1748 return false;
1749 }
1750
Dees_Troy2673cec2013-04-02 20:22:16 +00001751 gui_print("Restoring %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001752 Command = "dd bs=4096 if='" + Full_FileName + "' of=" + Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001753 LOGINFO("Restore command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001754 TWFunc::Exec_Cmd(Command);
Dees_Troy43d8b002012-09-17 16:00:01 -04001755 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001756}
1757
1758bool TWPartition::Restore_Flash_Image(string restore_folder) {
Vojtech Bocek05534202013-09-11 08:11:56 +02001759 string Full_FileName, Command;
Dees_Troy43d8b002012-09-17 16:00:01 -04001760
Dees_Troy2673cec2013-04-02 20:22:16 +00001761 gui_print("Restoring %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001762 Full_FileName = restore_folder + "/" + Backup_FileName;
1763 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
1764 Command = "erase_image " + MTD_Name;
Dees_Troy2673cec2013-04-02 20:22:16 +00001765 LOGINFO("Erase command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001766 TWFunc::Exec_Cmd(Command);
Dees_Troy43d8b002012-09-17 16:00:01 -04001767 Command = "flash_image " + MTD_Name + " '" + Full_FileName + "'";
Dees_Troy2673cec2013-04-02 20:22:16 +00001768 LOGINFO("Restore command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001769 TWFunc::Exec_Cmd(Command);
Dees_Troy43d8b002012-09-17 16:00:01 -04001770 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001771}
Dees_Troy5bf43922012-09-07 16:07:55 -04001772
1773bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy0550cfb2012-10-13 11:56:13 -04001774 bool ret = false, Was_Already_Mounted = false;
Dees_Troy51127312012-09-08 13:08:49 -04001775
Dees_Troyab10ee22012-09-21 14:27:30 -04001776 if (!Can_Be_Mounted && !Is_Encrypted)
Dees_Troy5bf43922012-09-07 16:07:55 -04001777 return false;
1778
Dees_Troy0550cfb2012-10-13 11:56:13 -04001779 Was_Already_Mounted = Is_Mounted();
Dees_Troy38bd7602012-09-14 13:33:53 -04001780 if (Removable || Is_Encrypted) {
1781 if (!Mount(false))
1782 return true;
1783 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04001784 return false;
Dees_Troy51127312012-09-08 13:08:49 -04001785
1786 ret = Get_Size_Via_statfs(Display_Error);
Dees_Troy0550cfb2012-10-13 11:56:13 -04001787 if (!ret || Size == 0) {
1788 if (!Get_Size_Via_df(Display_Error)) {
1789 if (!Was_Already_Mounted)
1790 UnMount(false);
Dees_Troy51127312012-09-08 13:08:49 -04001791 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04001792 }
1793 }
Dees_Troy51127312012-09-08 13:08:49 -04001794
Dees_Troy5bf43922012-09-07 16:07:55 -04001795 if (Has_Data_Media) {
1796 if (Mount(Display_Error)) {
Dees_Troy51127312012-09-08 13:08:49 -04001797 unsigned long long data_media_used, actual_data;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001798 du.add_relative_dir("media");
1799 Used = du.Get_Folder_Size("/data");
bigbiff bigbiffc7360dd2014-01-25 15:02:57 -05001800 du.clear_relative_dir("media");
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001801 Backup_Size = Used;
1802 int bak = (int)(Used / 1048576LLU);
Dees_Troy51127312012-09-08 13:08:49 -04001803 int fre = (int)(Free / 1048576LLU);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001804 LOGINFO("Data backup size is %iMB, free: %iMB.\n", bak, fre);
Dees_Troy0550cfb2012-10-13 11:56:13 -04001805 } else {
1806 if (!Was_Already_Mounted)
1807 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04001808 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04001809 }
Dees_Troye58d5262012-09-21 12:27:57 -04001810 } else if (Has_Android_Secure) {
1811 if (Mount(Display_Error))
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05001812 Backup_Size = du.Get_Folder_Size(Backup_Path);
Dees_Troy0550cfb2012-10-13 11:56:13 -04001813 else {
1814 if (!Was_Already_Mounted)
1815 UnMount(false);
Dees_Troye58d5262012-09-21 12:27:57 -04001816 return false;
Dees_Troy0550cfb2012-10-13 11:56:13 -04001817 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001818 }
Dees_Troy0550cfb2012-10-13 11:56:13 -04001819 if (!Was_Already_Mounted)
1820 UnMount(false);
Dees_Troy5bf43922012-09-07 16:07:55 -04001821 return true;
Dees_Troy51127312012-09-08 13:08:49 -04001822}
Dees_Troy38bd7602012-09-14 13:33:53 -04001823
1824void TWPartition::Find_Actual_Block_Device(void) {
1825 if (Is_Decrypted) {
1826 Actual_Block_Device = Decrypted_Block_Device;
Dees_Troy43d8b002012-09-17 16:00:01 -04001827 if (TWFunc::Path_Exists(Primary_Block_Device))
Dees_Troy38bd7602012-09-14 13:33:53 -04001828 Is_Present = true;
Dees_Troy43d8b002012-09-17 16:00:01 -04001829 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001830 Is_Present = true;
1831 Actual_Block_Device = Primary_Block_Device;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001832 return;
1833 }
1834 if (Is_Decrypted) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001835 } else if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy3f04d032012-10-07 18:20:09 -04001836 Actual_Block_Device = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -04001837 Is_Present = true;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001838 } else {
Dees_Troy38bd7602012-09-14 13:33:53 -04001839 Is_Present = false;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001840 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001841}
1842
1843void TWPartition::Recreate_Media_Folder(void) {
1844 string Command;
1845
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001846 #ifdef HAVE_SELINUX
1847 fixPermissions perms;
1848 #endif
1849
Dees_Troy38bd7602012-09-14 13:33:53 -04001850 if (!Mount(true)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001851 LOGERR("Unable to recreate /data/media folder.\n");
Dees_Troyb46a6842012-09-25 11:06:46 -04001852 } else if (!TWFunc::Path_Exists("/data/media")) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001853 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
Dees_Troy2673cec2013-04-02 20:22:16 +00001854 LOGINFO("Recreating /data/media folder.\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001855 mkdir("/data/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
bigbiff bigbiff6b600f92014-01-05 18:13:43 -05001856 #ifdef HAVE_SELINUX
1857 perms.fixDataInternalContexts();
1858 #endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001859 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troy38bd7602012-09-14 13:33:53 -04001860 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001861}
Dees_Troye58d5262012-09-21 12:27:57 -04001862
1863void TWPartition::Recreate_AndSec_Folder(void) {
Dees_Troye58d5262012-09-21 12:27:57 -04001864 if (!Has_Android_Secure)
1865 return;
Dees_Troy2673cec2013-04-02 20:22:16 +00001866 LOGINFO("Creating %s: %s\n", Backup_Display_Name.c_str(), Symlink_Path.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04001867 if (!Mount(true)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001868 LOGERR("Unable to recreate %s folder.\n", Backup_Name.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -04001869 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001870 LOGINFO("Recreating %s folder.\n", Backup_Name.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001871 PartitionManager.Mount_By_Path(Symlink_Mount_Point, true);
1872 mkdir(Symlink_Path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
1873 PartitionManager.UnMount_By_Path(Symlink_Mount_Point, true);
Dees_Troye58d5262012-09-21 12:27:57 -04001874 }
1875}