blob: a9d50917f6f070dbc492a51085f398b6e45c3717 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001/* Partition class for TWRP
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 *
17 * The code was written from scratch by Dees_Troy dees_troy at
18 * yahoo
19 *
20 * Copyright (c) 2012
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <sys/vfs.h>
Dees_Troy5bf43922012-09-07 16:07:55 -040028#include <sys/mount.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040029#include <unistd.h>
Dees_Troy51127312012-09-08 13:08:49 -040030#include <dirent.h>
Dees_Troy51a0e822012-09-05 15:24:24 -040031
Dees_Troy657c3092012-09-10 20:32:10 -040032#ifdef TW_INCLUDE_CRYPTO
33 #include "cutils/properties.h"
34#endif
35
Dees_Troy51a0e822012-09-05 15:24:24 -040036#include "variables.h"
37#include "common.h"
38#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040039#include "data.hpp"
Dees_Troy43d8b002012-09-17 16:00:01 -040040#include "twrp-functions.hpp"
Dees_Troy9df963c2012-09-26 08:58:12 -040041#include "makelist.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040042extern "C" {
Dees_Troy38bd7602012-09-14 13:33:53 -040043 #include "mtdutils/mtdutils.h"
44 #include "mtdutils/mounts.h"
Dees_Troyc51f1f92012-09-20 15:32:13 -040045 #include "extra-functions.h"
Dees_Troy5bf43922012-09-07 16:07:55 -040046}
Dees_Troy51a0e822012-09-05 15:24:24 -040047
48TWPartition::TWPartition(void) {
49 Can_Be_Mounted = false;
50 Can_Be_Wiped = false;
51 Wipe_During_Factory_Reset = false;
52 Wipe_Available_in_GUI = false;
53 Is_SubPartition = false;
Dees_Troy2691f9d2012-09-24 11:15:49 -040054 Has_SubPartition = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040055 SubPartition_Of = "";
56 Symlink_Path = "";
57 Symlink_Mount_Point = "";
58 Mount_Point = "";
Dees_Troye58d5262012-09-21 12:27:57 -040059 Backup_Path = "";
Dees_Troy38bd7602012-09-14 13:33:53 -040060 Actual_Block_Device = "";
61 Primary_Block_Device = "";
Dees_Troy51a0e822012-09-05 15:24:24 -040062 Alternate_Block_Device = "";
63 Removable = false;
64 Is_Present = false;
65 Length = 0;
66 Size = 0;
67 Used = 0;
68 Free = 0;
69 Backup_Size = 0;
70 Can_Be_Encrypted = false;
71 Is_Encrypted = false;
72 Is_Decrypted = false;
73 Decrypted_Block_Device = "";
74 Display_Name = "";
75 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -040076 Backup_FileName = "";
Dees_Troy38bd7602012-09-14 13:33:53 -040077 MTD_Name = "";
Dees_Troy51a0e822012-09-05 15:24:24 -040078 Backup_Method = NONE;
79 Has_Data_Media = false;
Dees_Troye58d5262012-09-21 12:27:57 -040080 Has_Android_Secure = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040081 Is_Storage = false;
82 Storage_Path = "";
83 Current_File_System = "";
84 Fstab_File_System = "";
85 Format_Block_Size = 0;
86}
87
88TWPartition::~TWPartition(void) {
89 // Do nothing
90}
91
Dees_Troy5bf43922012-09-07 16:07:55 -040092bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
93 char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH];
94 int line_len = Line.size(), index = 0, item_index = 0;
95 char* ptr;
Dees_Troy51127312012-09-08 13:08:49 -040096 string Flags;
Dees_Troy5bf43922012-09-07 16:07:55 -040097
98 strncpy(full_line, Line.c_str(), line_len);
99
Dees_Troy51127312012-09-08 13:08:49 -0400100 for (index = 0; index < line_len; index++) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400101 if (full_line[index] <= 32)
102 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -0400103 }
104 string mount_pt(full_line);
105 Mount_Point = mount_pt;
Dees_Troy9df963c2012-09-26 08:58:12 -0400106 LOGI("Processing '%s'\n", mount_pt);
Dees_Troye58d5262012-09-21 12:27:57 -0400107 Backup_Path = Mount_Point;
Dees_Troy5bf43922012-09-07 16:07:55 -0400108 index = Mount_Point.size();
109 while (index < line_len) {
110 while (index < line_len && full_line[index] == '\0')
111 index++;
112 if (index >= line_len)
113 continue;
114 ptr = full_line + index;
115 if (item_index == 0) {
116 // File System
117 Fstab_File_System = ptr;
118 Current_File_System = ptr;
119 item_index++;
120 } else if (item_index == 1) {
121 // Primary Block Device
Dees_Troy38bd7602012-09-14 13:33:53 -0400122 if (Fstab_File_System == "mtd" || Fstab_File_System == "yaffs2") {
123 Primary_Block_Device = ptr;
124 Find_MTD_Block_Device(Primary_Block_Device);
125 } else if (*ptr != '/') {
Dees_Troy5bf43922012-09-07 16:07:55 -0400126 if (Display_Error)
127 LOGE("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
128 else
129 LOGI("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
130 return 0;
Dees_Troy38bd7602012-09-14 13:33:53 -0400131 } else {
132 Primary_Block_Device = ptr;
133 Find_Real_Block_Device(Primary_Block_Device, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400134 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400135 item_index++;
136 } else if (item_index > 1) {
137 if (*ptr == '/') {
138 // Alternate Block Device
139 Alternate_Block_Device = ptr;
140 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
141 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
142 // Partition length
143 ptr += 7;
144 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400145 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
146 // Custom flags, save for later so that new values aren't overwritten by defaults
147 ptr += 6;
148 Flags = ptr;
Dees_Troy38bd7602012-09-14 13:33:53 -0400149 } else if (strlen(ptr) == 4 && (strncmp(ptr, "NULL", 4) == 0 || strncmp(ptr, "null", 4) == 0 || strncmp(ptr, "null", 4) == 0)) {
150 // Do nothing
Dees_Troy5bf43922012-09-07 16:07:55 -0400151 } else {
152 // Unhandled data
Dees_Troyab10ee22012-09-21 14:27:30 -0400153 LOGI("Unhandled fstab information: '%s', %i, line: '%s'\n", ptr, index, Line.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400154 }
155 }
156 while (index < line_len && full_line[index] != '\0')
157 index++;
158 }
159
160 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
161 if (Display_Error)
162 LOGE("Unknown File System: '%s'\n", Fstab_File_System.c_str());
163 else
164 LOGI("Unknown File System: '%s'\n", Fstab_File_System.c_str());
165 return 0;
166 } else if (Is_File_System(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400167 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400168 Setup_File_System(Display_Error);
169 if (Mount_Point == "/system") {
170 Display_Name = "System";
171 Wipe_Available_in_GUI = true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400172 MTD_Name = "system";
Dees_Troy5bf43922012-09-07 16:07:55 -0400173 } else if (Mount_Point == "/data") {
174 Display_Name = "Data";
175 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400176 Wipe_During_Factory_Reset = true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400177 MTD_Name = "userdata";
Dees_Troy5bf43922012-09-07 16:07:55 -0400178#ifdef RECOVERY_SDCARD_ON_DATA
179 Has_Data_Media = true;
Dees_Troy51127312012-09-08 13:08:49 -0400180 Is_Storage = true;
181 Storage_Path = "/data/media";
Dees_Troyb46a6842012-09-25 11:06:46 -0400182 Recreate_Media_Folder();
Dees_Troy657c3092012-09-10 20:32:10 -0400183 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
184 Make_Dir("/emmc", Display_Error);
185 Symlink_Path = "/data/media";
186 Symlink_Mount_Point = "/emmc";
187 } else {
188 Make_Dir("/sdcard", Display_Error);
189 Symlink_Path = "/data/media";
190 Symlink_Mount_Point = "/sdcard";
191 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400192#endif
193#ifdef TW_INCLUDE_CRYPTO
194 Can_Be_Encrypted = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400195 char crypto_blkdev[255];
196 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
197 if (strcmp(crypto_blkdev, "error") != 0) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400198 DataManager::SetValue(TW_DATA_BLK_DEVICE, Primary_Block_Device);
Dees_Troy657c3092012-09-10 20:32:10 -0400199 DataManager::SetValue(TW_IS_DECRYPTED, 1);
200 Is_Encrypted = true;
201 Is_Decrypted = true;
202 Decrypted_Block_Device = crypto_blkdev;
203 LOGI("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
204 } else if (!Mount(false)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400205 Is_Encrypted = true;
206 Is_Decrypted = false;
207 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
208 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
209 DataManager::SetValue("tw_crypto_display", "");
Dees_Troy51127312012-09-08 13:08:49 -0400210 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400211#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400212 } else if (Mount_Point == "/cache") {
213 Display_Name = "Cache";
214 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400215 Wipe_During_Factory_Reset = true;
Dees_Troy38bd7602012-09-14 13:33:53 -0400216 MTD_Name = "cache";
Dees_Troyb46a6842012-09-25 11:06:46 -0400217 if (!TWFunc::Path_Exists("/cache/recovery")) {
218 LOGI("Recreating /cache/recovery folder.\n");
219 TWFunc::Recursive_Mkdir("/cache/recovery");
220 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400221 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400222 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400223 Display_Name = "DataData";
224 Is_SubPartition = true;
225 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400226 DataManager::SetValue(TW_HAS_DATADATA, 1);
227 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400228 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400229 Display_Name = "SD-Ext";
230 Wipe_Available_in_GUI = true;
Dees_Troyc51f1f92012-09-20 15:32:13 -0400231 Removable = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400232 }
233#ifdef TW_EXTERNAL_STORAGE_PATH
234 if (Mount_Point == EXPAND(TW_EXTERNAL_STORAGE_PATH)) {
235 Is_Storage = true;
236 Storage_Path = EXPAND(TW_EXTERNAL_STORAGE_PATH);
Dees_Troyc51f1f92012-09-20 15:32:13 -0400237 Removable = true;
Dees_Troy8170a922012-09-18 15:40:25 -0400238 }
239#else
240 if (Mount_Point == "/sdcard") {
241 Is_Storage = true;
242 Storage_Path = "/sdcard";
Dees_Troyc51f1f92012-09-20 15:32:13 -0400243 Removable = true;
Dees_Troye58d5262012-09-21 12:27:57 -0400244#ifndef RECOVERY_SDCARD_ON_DATA
245 Setup_AndSec();
246#endif
Dees_Troy8170a922012-09-18 15:40:25 -0400247 }
248#endif
249#ifdef TW_INTERNAL_STORAGE_PATH
250 if (Mount_Point == EXPAND(TW_INTERNAL_STORAGE_PATH)) {
251 Is_Storage = true;
252 Storage_Path = EXPAND(TW_INTERNAL_STORAGE_PATH);
Dees_Troye58d5262012-09-21 12:27:57 -0400253#ifndef RECOVERY_SDCARD_ON_DATA
254 Setup_AndSec();
255#endif
Dees_Troy8170a922012-09-18 15:40:25 -0400256 }
257#else
258 if (Mount_Point == "/emmc") {
259 Is_Storage = true;
260 Storage_Path = "/emmc";
Dees_Troye58d5262012-09-21 12:27:57 -0400261#ifndef RECOVERY_SDCARD_ON_DATA
262 Setup_AndSec();
263#endif
Dees_Troy8170a922012-09-18 15:40:25 -0400264 }
265#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400266 } else if (Is_Image(Fstab_File_System)) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400267 Find_Actual_Block_Device();
Dees_Troy5bf43922012-09-07 16:07:55 -0400268 Setup_Image(Display_Error);
269 if (Mount_Point == "/boot") {
Dees_Troy38bd7602012-09-14 13:33:53 -0400270 MTD_Name = "boot";
Dees_Troy5bf43922012-09-07 16:07:55 -0400271 int backup_display_size = (int)(Backup_Size / 1048576LLU);
272 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
273 if (Backup_Size == 0) {
274 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 0);
275 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
276 } else
277 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 1);
278 } else if (Mount_Point == "/recovery") {
Dees_Troy38bd7602012-09-14 13:33:53 -0400279 MTD_Name = "recovery";
Dees_Troy5bf43922012-09-07 16:07:55 -0400280 int backup_display_size = (int)(Backup_Size / 1048576LLU);
281 DataManager::SetValue(TW_BACKUP_RECOVERY_SIZE, backup_display_size);
282 if (Backup_Size == 0) {
283 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 0);
284 DataManager::SetValue(TW_BACKUP_RECOVERY_VAR, 0);
285 } else
286 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 1);
287 }
288 }
289
Dees_Troy51127312012-09-08 13:08:49 -0400290 // Process any custom flags
291 if (Flags.size() > 0)
292 Process_Flags(Flags, Display_Error);
293
294 return true;
295}
296
297bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
298 char flags[MAX_FSTAB_LINE_LENGTH];
299 int flags_len, index = 0;
300 char* ptr;
301
302 strcpy(flags, Flags.c_str());
303 flags_len = Flags.size();
304 for (index = 0; index < flags_len; index++) {
305 if (flags[index] == ';')
306 flags[index] = '\0';
307 }
308
309 index = 0;
310 while (index < flags_len) {
311 while (index < flags_len && flags[index] == '\0')
312 index++;
313 if (index >= flags_len)
314 continue;
315 ptr = flags + index;
316 if (strcmp(ptr, "removable") == 0) {
317 Removable = true;
318 } else if (strcmp(ptr, "storage") == 0) {
319 Is_Storage = true;
Dees_Troy63c8df72012-09-10 14:02:05 -0400320 } else if (strcmp(ptr, "canbewiped") == 0) {
321 Can_Be_Wiped = true;
322 } else if (strcmp(ptr, "wipeingui") == 0) {
323 Can_Be_Wiped = true;
324 Wipe_Available_in_GUI = true;
325 } else if (strcmp(ptr, "wipeduringfactoryreset") == 0) {
326 Can_Be_Wiped = true;
327 Wipe_Available_in_GUI = true;
328 Wipe_During_Factory_Reset = true;
Dees_Troy51127312012-09-08 13:08:49 -0400329 } else if (strlen(ptr) > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) {
330 ptr += 13;
331 Is_SubPartition = true;
332 SubPartition_Of = ptr;
333 } else if (strlen(ptr) > 8 && strncmp(ptr, "symlink=", 8) == 0) {
334 ptr += 8;
335 Symlink_Path = ptr;
336 } else if (strlen(ptr) > 8 && strncmp(ptr, "display=", 8) == 0) {
337 ptr += 8;
338 Display_Name = ptr;
339 } else if (strlen(ptr) > 10 && strncmp(ptr, "blocksize=", 10) == 0) {
340 ptr += 10;
341 Format_Block_Size = atoi(ptr);
342 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
343 ptr += 7;
344 Length = atoi(ptr);
345 } else {
346 if (Display_Error)
347 LOGE("Unhandled flag: '%s'\n", ptr);
348 else
349 LOGI("Unhandled flag: '%s'\n", ptr);
350 }
351 while (index < flags_len && flags[index] != '\0')
352 index++;
353 }
354 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400355}
356
Dees_Troy5bf43922012-09-07 16:07:55 -0400357bool TWPartition::Is_File_System(string File_System) {
358 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400359 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400360 File_System == "ext4" ||
361 File_System == "vfat" ||
362 File_System == "ntfs" ||
363 File_System == "yaffs2" ||
364 File_System == "auto")
365 return true;
366 else
367 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400368}
369
Dees_Troy5bf43922012-09-07 16:07:55 -0400370bool TWPartition::Is_Image(string File_System) {
371 if (File_System == "emmc" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400372 File_System == "mtd")
Dees_Troy5bf43922012-09-07 16:07:55 -0400373 return true;
374 else
375 return false;
376}
377
Dees_Troy51127312012-09-08 13:08:49 -0400378bool TWPartition::Make_Dir(string Path, bool Display_Error) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400379 if (!TWFunc::Path_Exists(Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400380 if (mkdir(Path.c_str(), 0777) == -1) {
381 if (Display_Error)
382 LOGE("Can not create '%s' folder.\n", Path.c_str());
383 else
384 LOGI("Can not create '%s' folder.\n", Path.c_str());
385 return false;
386 } else {
387 LOGI("Created '%s' folder.\n", Path.c_str());
388 return true;
389 }
390 }
391 return true;
392}
393
Dees_Troy5bf43922012-09-07 16:07:55 -0400394void TWPartition::Setup_File_System(bool Display_Error) {
395 struct statfs st;
396
397 Can_Be_Mounted = true;
398 Can_Be_Wiped = true;
399
Dees_Troy5bf43922012-09-07 16:07:55 -0400400 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400401 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400402 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
403 Backup_Name = Display_Name;
404 Backup_Method = FILES;
405}
406
407void TWPartition::Setup_Image(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400408 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
409 Backup_Name = Display_Name;
410 if (Fstab_File_System == "emmc")
411 Backup_Method = DD;
412 else if (Fstab_File_System == "mtd")
413 Backup_Method = FLASH_UTILS;
414 else
415 LOGI("Unhandled file system '%s' on image '%s'\n", Fstab_File_System.c_str(), Display_Name.c_str());
416 if (Find_Partition_Size()) {
417 Used = Size;
418 Backup_Size = Size;
Dees_Troy51a0e822012-09-05 15:24:24 -0400419 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400420 if (Display_Error)
Dees_Troy38bd7602012-09-14 13:33:53 -0400421 LOGE("Unable to find parition size for '%s'\n", Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400422 else
Dees_Troy38bd7602012-09-14 13:33:53 -0400423 LOGI("Unable to find parition size for '%s'\n", Mount_Point.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400424 }
425}
426
Dees_Troye58d5262012-09-21 12:27:57 -0400427void TWPartition::Setup_AndSec(void) {
428 Backup_Name = "and-sec";
429 Has_Android_Secure = true;
430 Symlink_Path = Mount_Point + "/.android_secure";
431 Symlink_Mount_Point = "/and-sec";
432 Backup_Path = Symlink_Mount_Point;
433 Make_Dir("/and-sec", true);
434 Recreate_AndSec_Folder();
435}
436
Dees_Troy5bf43922012-09-07 16:07:55 -0400437void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
438 char device[512], realDevice[512];
439
440 strcpy(device, Block.c_str());
441 memset(realDevice, 0, sizeof(realDevice));
442 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
443 {
444 strcpy(device, realDevice);
445 memset(realDevice, 0, sizeof(realDevice));
446 }
447
448 if (device[0] != '/') {
449 if (Display_Error)
450 LOGE("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
451 else
452 LOGI("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
453 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400454 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400455 Block = device;
456 return;
457 }
458}
459
Dees_Troy38bd7602012-09-14 13:33:53 -0400460bool TWPartition::Find_MTD_Block_Device(string MTD_Name) {
461 FILE *fp = NULL;
462 char line[255];
463
464 fp = fopen("/proc/mtd", "rt");
465 if (fp == NULL) {
466 LOGE("Device does not support /proc/mtd\n");
467 return false;
468 }
469
470 while (fgets(line, sizeof(line), fp) != NULL)
471 {
472 char device[32], label[32];
473 unsigned long size = 0;
474 char* fstype = NULL;
475 int deviceId;
476
477 sscanf(line, "%s %lx %*s %*c%s", device, &size, label);
478
479 // Skip header and blank lines
480 if ((strcmp(device, "dev:") == 0) || (strlen(line) < 8))
481 continue;
482
483 // Strip off the trailing " from the label
484 label[strlen(label)-1] = '\0';
485
486 if (strcmp(label, MTD_Name.c_str()) == 0) {
487 // We found our device
488 // Strip off the trailing : from the device
489 device[strlen(device)-1] = '\0';
490 if (sscanf(device,"mtd%d", &deviceId) == 1) {
491 sprintf(device, "/dev/block/mtdblock%d", deviceId);
492 Primary_Block_Device = device;
493 }
494 }
495 }
496 fclose(fp);
497
498 return false;
499}
500
Dees_Troy51127312012-09-08 13:08:49 -0400501bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
502 struct statfs st;
503 string Local_Path = Mount_Point + "/.";
504
505 if (!Mount(Display_Error))
506 return false;
507
508 if (statfs(Local_Path.c_str(), &st) != 0) {
509 if (!Removable) {
510 if (Display_Error)
511 LOGE("Unable to statfs '%s'\n", Local_Path.c_str());
512 else
513 LOGI("Unable to statfs '%s'\n", Local_Path.c_str());
514 }
515 return false;
516 }
517 Size = (st.f_blocks * st.f_bsize);
518 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
519 Free = (st.f_bfree * st.f_bsize);
520 Backup_Size = Used;
521 return true;
522}
523
524bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400525 FILE* fp;
526 char command[255], line[512];
527 int include_block = 1;
528 unsigned int min_len;
529
530 if (!Mount(Display_Error))
531 return false;
532
Dees_Troy38bd7602012-09-14 13:33:53 -0400533 min_len = Actual_Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -0400534 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400535 system(command);
Dees_Troy51127312012-09-08 13:08:49 -0400536 fp = fopen("/tmp/dfoutput.txt", "rt");
537 if (fp == NULL) {
538 LOGI("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400539 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400540 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400541
542 while (fgets(line, sizeof(line), fp) != NULL)
543 {
544 unsigned long blocks, used, available;
545 char device[64];
546 char tmpString[64];
547
548 if (strncmp(line, "Filesystem", 10) == 0)
549 continue;
550 if (strlen(line) < min_len) {
551 include_block = 0;
552 continue;
553 }
554 if (include_block) {
555 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
556 } else {
557 // The device block string is so long that the df information is on the next line
558 int space_count = 0;
Dees_Troye58d5262012-09-21 12:27:57 -0400559 sprintf(tmpString, "/dev/block/%s", Actual_Block_Device.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400560 while (tmpString[space_count] == 32)
561 space_count++;
562 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
563 }
564
565 // Adjust block size to byte size
566 Size = blocks * 1024ULL;
567 Used = used * 1024ULL;
568 Free = available * 1024ULL;
569 Backup_Size = Used;
570 }
571 fclose(fp);
572 return true;
573}
574
Dees_Troy5bf43922012-09-07 16:07:55 -0400575bool TWPartition::Find_Partition_Size(void) {
576 FILE* fp;
577 char line[512];
578 string tmpdevice;
579
580 // In this case, we'll first get the partitions we care about (with labels)
581 fp = fopen("/proc/partitions", "rt");
582 if (fp == NULL)
583 return false;
584
585 while (fgets(line, sizeof(line), fp) != NULL)
586 {
587 unsigned long major, minor, blocks;
588 char device[512];
589 char tmpString[64];
590
Dees_Troy63c8df72012-09-10 14:02:05 -0400591 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400592 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
593
594 tmpdevice = "/dev/block/";
595 tmpdevice += device;
Dees_Troy38bd7602012-09-14 13:33:53 -0400596 if (tmpdevice == Primary_Block_Device || tmpdevice == Alternate_Block_Device) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400597 // Adjust block size to byte size
598 Size = blocks * 1024ULL;
599 fclose(fp);
600 return true;
601 }
602 }
603 fclose(fp);
604 return false;
605}
606
Dees_Troy5bf43922012-09-07 16:07:55 -0400607void TWPartition::Flip_Block_Device(void) {
608 string temp;
609
610 temp = Alternate_Block_Device;
Dees_Troy38bd7602012-09-14 13:33:53 -0400611 Primary_Block_Device = Alternate_Block_Device;
Dees_Troy5bf43922012-09-07 16:07:55 -0400612 Alternate_Block_Device = temp;
613}
614
615bool TWPartition::Is_Mounted(void) {
616 if (!Can_Be_Mounted)
617 return false;
618
619 struct stat st1, st2;
620 string test_path;
621
622 // Check to see if the mount point directory exists
623 test_path = Mount_Point + "/.";
624 if (stat(test_path.c_str(), &st1) != 0) return false;
625
626 // Check to see if the directory above the mount point exists
627 test_path = Mount_Point + "/../.";
628 if (stat(test_path.c_str(), &st2) != 0) return false;
629
630 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
631 int ret = (st1.st_dev != st2.st_dev) ? true : false;
632
633 return ret;
634}
635
636bool TWPartition::Mount(bool Display_Error) {
637 if (Is_Mounted()) {
638 return true;
639 } else if (!Can_Be_Mounted) {
640 return false;
641 }
Dees_Troy38bd7602012-09-14 13:33:53 -0400642
643 Find_Actual_Block_Device();
644
645 // Check the current file system before mounting
646 Check_FS_Type();
647
648 if (mount(Actual_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
649 if (Display_Error)
650 LOGE("Unable to mount '%s'\n", Mount_Point.c_str());
651 else
652 LOGI("Unable to mount '%s'\n", Mount_Point.c_str());
653 return false;
654 } else {
655 if (Removable)
656 Update_Size(Display_Error);
657
658 if (!Symlink_Mount_Point.empty()) {
659 string Command;
660
661 Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
Dees_Troy43d8b002012-09-17 16:00:01 -0400662 system(Command.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400663 }
Dees_Troy38bd7602012-09-14 13:33:53 -0400664 return true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400665 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400666 return true;
667}
668
669bool TWPartition::UnMount(bool Display_Error) {
670 if (Is_Mounted()) {
671 int never_unmount_system;
672
673 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
674 if (never_unmount_system == 1 && Mount_Point == "/system")
675 return true; // Never unmount system if you're not supposed to unmount it
676
Dees_Troy38bd7602012-09-14 13:33:53 -0400677 if (!Symlink_Mount_Point.empty())
678 umount(Symlink_Mount_Point.c_str());
679
Dees_Troy5bf43922012-09-07 16:07:55 -0400680 if (umount(Mount_Point.c_str()) != 0) {
681 if (Display_Error)
682 LOGE("Unable to unmount '%s'\n", Mount_Point.c_str());
683 else
684 LOGI("Unable to unmount '%s'\n", Mount_Point.c_str());
685 return false;
686 } else
687 return true;
688 } else {
689 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400690 }
691}
692
693bool TWPartition::Wipe() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400694 if (!Can_Be_Wiped) {
695 LOGE("Partition '%s' cannot be wiped.\n", Mount_Point.c_str());
696 return false;
697 }
698
Dees_Troyc51f1f92012-09-20 15:32:13 -0400699 if (Mount_Point == "/cache")
700 tmplog_offset = 0;
701
Dees_Troy38bd7602012-09-14 13:33:53 -0400702 if (Has_Data_Media)
703 return Wipe_Data_Without_Wiping_Media();
704
705 int check;
706 DataManager::GetValue(TW_RM_RF_VAR, check);
707 if (check)
708 return Wipe_RMRF();
709
710 if (Current_File_System == "ext4")
711 return Wipe_EXT4();
712
713 if (Current_File_System == "ext2" || Current_File_System == "ext3")
714 return Wipe_EXT23();
715
716 if (Current_File_System == "vfat")
717 return Wipe_FAT();
718
719 if (Current_File_System == "yaffs2")
720 return Wipe_MTD();
721
722 LOGE("Unable to wipe '%s' -- unknown file system '%s'\n", Mount_Point.c_str(), Current_File_System.c_str());
723 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400724}
725
Dees_Troye58d5262012-09-21 12:27:57 -0400726bool TWPartition::Wipe_AndSec(void) {
727 if (!Has_Android_Secure)
728 return false;
729
730 char cmd[512];
731
732 if (!Mount(true))
733 return false;
734
735 ui_print("Using rm -rf on .android_secure\n");
736 sprintf(cmd, "rm -rf %s/.android_secure/* && rm -rf %s/.android_secure/.*", Mount_Point.c_str(), Mount_Point.c_str());
737
738 LOGI("rm -rf command is: '%s'\n", cmd);
739 system(cmd);
740 return true;
741}
742
Dees_Troy51a0e822012-09-05 15:24:24 -0400743bool TWPartition::Backup(string backup_folder) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400744 if (Backup_Method == FILES)
745 return Backup_Tar(backup_folder);
746 else if (Backup_Method == DD)
747 return Backup_DD(backup_folder);
748 else if (Backup_Method == FLASH_UTILS)
749 return Backup_Dump_Image(backup_folder);
750 LOGE("Unknown backup method for '%s'\n", Mount_Point.c_str());
751 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400752}
753
Dees_Troy43d8b002012-09-17 16:00:01 -0400754bool TWPartition::Check_MD5(string restore_folder) {
755 string Full_Filename;
756 char split_filename[512];
757 int index = 0;
758
759 Full_Filename = restore_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -0400760 if (!TWFunc::Path_Exists(Full_Filename)) {
761 // This is a split archive, we presume
762 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
763 while (index < 1000 && TWFunc::Path_Exists(split_filename)) {
764 if (TWFunc::Check_MD5(split_filename) == 0) {
765 LOGE("MD5 failed to match on '%s'.\n", split_filename);
766 return false;
767 }
768 index++;
769 sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
Dees_Troy43d8b002012-09-17 16:00:01 -0400770 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400771 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -0400772 } else {
773 // Single file archive
774 if (TWFunc::Check_MD5(Full_Filename) == 0) {
775 LOGE("MD5 failed to match on '%s'.\n", split_filename);
776 return false;
777 } else
778 return true;
779 }
780 return false;
781}
782
Dees_Troy51a0e822012-09-05 15:24:24 -0400783bool TWPartition::Restore(string restore_folder) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400784 if (Backup_Method == FILES)
785 return Restore_Tar(restore_folder);
786 else if (Backup_Method == DD)
787 return Restore_DD(restore_folder);
788 else if (Backup_Method == FLASH_UTILS)
789 return Restore_Flash_Image(restore_folder);
790 LOGE("Unknown restore method for '%s'\n", Mount_Point.c_str());
791 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400792}
793
794string TWPartition::Backup_Method_By_Name() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400795 if (Backup_Method == NONE)
796 return "none";
797 else if (Backup_Method == FILES)
798 return "files";
799 else if (Backup_Method == DD)
800 return "dd";
801 else if (Backup_Method == FLASH_UTILS)
802 return "flash_utils";
803 else
804 return "undefined";
805 return "ERROR!";
Dees_Troy51a0e822012-09-05 15:24:24 -0400806}
807
808bool TWPartition::Decrypt(string Password) {
809 LOGI("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -0400810 // Is this needed?
Dees_Troy51a0e822012-09-05 15:24:24 -0400811 return 1;
812}
813
814bool TWPartition::Wipe_Encryption() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400815 bool Save_Data_Media = Has_Data_Media;
816
817 if (!UnMount(true))
818 return false;
819
820 Current_File_System = Fstab_File_System;
821 Is_Encrypted = false;
822 Is_Decrypted = false;
823 Decrypted_Block_Device = "";
824 Has_Data_Media = false;
825 if (Wipe()) {
826 Has_Data_Media = Save_Data_Media;
827 if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
828 Recreate_Media_Folder();
829 }
Dees_Troyb46a6842012-09-25 11:06:46 -0400830 ui_print("You may need to reboot recovery to be able to use /data again.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -0400831 return true;
832 } else {
833 Has_Data_Media = Save_Data_Media;
834 LOGE("Unable to format to remove encryption.\n");
835 return false;
836 }
837 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400838}
839
840void TWPartition::Check_FS_Type() {
Dees_Troy5bf43922012-09-07 16:07:55 -0400841 FILE *fp;
842 string blkCommand;
843 char blkOutput[255];
844 char* blk;
845 char* arg;
846 char* ptr;
847
848 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd")
849 return; // Running blkid on some mtd devices causes a massive crash
850
Dees_Troy38bd7602012-09-14 13:33:53 -0400851 Find_Actual_Block_Device();
Dees_Troy8170a922012-09-18 15:40:25 -0400852 if (!Is_Present)
853 return;
Dees_Troy51127312012-09-08 13:08:49 -0400854
Dees_Troy8170a922012-09-18 15:40:25 -0400855 if (TWFunc::Path_Exists("/tmp/blkidoutput.txt"))
856 system("rm /tmp/blkidoutput.txt");
857
858 blkCommand = "blkid " + Actual_Block_Device + " > /tmp/blkidoutput.txt";
Dees_Troy43d8b002012-09-17 16:00:01 -0400859 system(blkCommand.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400860 fp = fopen("/tmp/blkidoutput.txt", "rt");
Dees_Troy8170a922012-09-18 15:40:25 -0400861 if (fp == NULL)
862 return;
Dees_Troy5bf43922012-09-07 16:07:55 -0400863 while (fgets(blkOutput, sizeof(blkOutput), fp) != NULL)
864 {
865 blk = blkOutput;
866 ptr = blkOutput;
Dees_Troy63c8df72012-09-10 14:02:05 -0400867 while (*ptr > 32 && *ptr != ':') ptr++;
868 if (*ptr == 0) continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400869 *ptr = 0;
870
871 // Increment by two, but verify that we don't hit a NULL
872 ptr++;
Dees_Troy63c8df72012-09-10 14:02:05 -0400873 if (*ptr != 0) ptr++;
Dees_Troy5bf43922012-09-07 16:07:55 -0400874
875 // Now, find the TYPE field
876 while (1)
877 {
878 arg = ptr;
Dees_Troy63c8df72012-09-10 14:02:05 -0400879 while (*ptr > 32) ptr++;
Dees_Troy5bf43922012-09-07 16:07:55 -0400880 if (*ptr != 0)
881 {
882 *ptr = 0;
883 ptr++;
884 }
885
886 if (strlen(arg) > 6)
887 {
888 if (memcmp(arg, "TYPE=\"", 6) == 0) break;
889 }
890
891 if (*ptr == 0)
892 {
893 arg = NULL;
894 break;
895 }
896 }
897
898 if (arg && strlen(arg) > 7)
899 {
900 arg += 6; // Skip the TYPE=" portion
901 arg[strlen(arg)-1] = '\0'; // Drop the tail quote
902 }
903 else
904 continue;
905
Dees_Troy63c8df72012-09-10 14:02:05 -0400906 if (strcmp(Current_File_System.c_str(), arg) != 0) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400907 LOGI("'%s' was '%s' now set to '%s'\n", Mount_Point.c_str(), Current_File_System.c_str(), arg);
908 Current_File_System = arg;
909 }
910 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400911 fclose(fp);
Dees_Troy51a0e822012-09-05 15:24:24 -0400912 return;
913}
914
915bool TWPartition::Wipe_EXT23() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400916 if (!UnMount(true))
917 return false;
918
Dees_Troy43d8b002012-09-17 16:00:01 -0400919 if (TWFunc::Path_Exists("/sbin/mke2fs")) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400920 char command[512];
921
922 ui_print("Formatting %s using mke2fs...\n", Display_Name.c_str());
923 Find_Actual_Block_Device();
924 sprintf(command, "mke2fs -t %s -m 0 %s", Current_File_System.c_str(), Actual_Block_Device.c_str());
925 LOGI("mke2fs command: %s\n", command);
Dees_Troy43d8b002012-09-17 16:00:01 -0400926 if (system(command) == 0) {
Dees_Troye58d5262012-09-21 12:27:57 -0400927 Recreate_AndSec_Folder();
Dees_Troy38bd7602012-09-14 13:33:53 -0400928 ui_print("Done.\n");
929 return true;
930 } else {
931 LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
932 return false;
933 }
934 } else
935 return Wipe_RMRF();
936
937 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400938}
939
940bool TWPartition::Wipe_EXT4() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400941 if (!UnMount(true))
942 return false;
943
Dees_Troy43d8b002012-09-17 16:00:01 -0400944 if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400945 string Command;
946
947 ui_print("Formatting %s using make_ext4fs...\n", Display_Name.c_str());
948 Find_Actual_Block_Device();
949 Command = "make_ext4fs";
950 if (!Is_Decrypted && Length != 0) {
951 // Only use length if we're not decrypted
952 char len[32];
953 sprintf(len, "%i", Length);
954 Command += " -l ";
955 Command += len;
956 }
957 Command += " " + Actual_Block_Device;
958 LOGI("make_ext4fs command: %s\n", Command.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400959 if (system(Command.c_str()) == 0) {
Dees_Troye58d5262012-09-21 12:27:57 -0400960 Recreate_AndSec_Folder();
Dees_Troy38bd7602012-09-14 13:33:53 -0400961 ui_print("Done.\n");
962 return true;
963 } else {
964 LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
965 return false;
966 }
967 } else
968 return Wipe_EXT23();
969
970 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400971}
972
973bool TWPartition::Wipe_FAT() {
Dees_Troy38bd7602012-09-14 13:33:53 -0400974 char command[512];
975
Dees_Troy43d8b002012-09-17 16:00:01 -0400976 if (TWFunc::Path_Exists("/sbin/mkdosfs")) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400977 if (!UnMount(true))
978 return false;
979
980 ui_print("Formatting %s using mkdosfs...\n", Display_Name.c_str());
981 Find_Actual_Block_Device();
982 sprintf(command,"mkdosfs %s", Actual_Block_Device.c_str()); // use mkdosfs to format it
Dees_Troy43d8b002012-09-17 16:00:01 -0400983 if (system(command) == 0) {
Dees_Troye58d5262012-09-21 12:27:57 -0400984 Recreate_AndSec_Folder();
Dees_Troy38bd7602012-09-14 13:33:53 -0400985 ui_print("Done.\n");
986 return true;
987 } else {
988 LOGE("Unable to wipe '%s'.\n", Mount_Point.c_str());
989 return false;
990 }
991 return true;
992 }
993 else
994 return Wipe_RMRF();
995
996 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400997}
998
Dees_Troy38bd7602012-09-14 13:33:53 -0400999bool TWPartition::Wipe_MTD() {
1000 if (!UnMount(true))
1001 return false;
1002
1003 ui_print("MTD Formatting \"%s\"\n", MTD_Name.c_str());
1004
1005 mtd_scan_partitions();
1006 const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
1007 if (mtd == NULL) {
1008 LOGE("No mtd partition named '%s'", MTD_Name.c_str());
1009 return false;
1010 }
1011
1012 MtdWriteContext* ctx = mtd_write_partition(mtd);
1013 if (ctx == NULL) {
1014 LOGE("Can't write '%s', failed to format.", MTD_Name.c_str());
1015 return false;
1016 }
1017 if (mtd_erase_blocks(ctx, -1) == -1) {
1018 mtd_write_close(ctx);
1019 LOGE("Failed to format '%s'", MTD_Name.c_str());
1020 return false;
1021 }
1022 if (mtd_write_close(ctx) != 0) {
1023 LOGE("Failed to close '%s'", MTD_Name.c_str());
1024 return false;
1025 }
Dees_Troye58d5262012-09-21 12:27:57 -04001026 Recreate_AndSec_Folder();
Dees_Troy38bd7602012-09-14 13:33:53 -04001027 ui_print("Done.\n");
1028 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001029}
1030
1031bool TWPartition::Wipe_RMRF() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001032 char cmd[512];
1033
1034 if (!Mount(true))
1035 return false;
1036
Dees_Troye58d5262012-09-21 12:27:57 -04001037 ui_print("Using rm -rf on '%s'\n", Mount_Point.c_str());
1038 sprintf(cmd, "rm -rf %s/* && rm -rf %s/.*", Mount_Point.c_str(), Mount_Point.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001039
1040 LOGI("rm -rf command is: '%s'\n", cmd);
Dees_Troy43d8b002012-09-17 16:00:01 -04001041 system(cmd);
Dees_Troye58d5262012-09-21 12:27:57 -04001042 Recreate_AndSec_Folder();
Dees_Troy38bd7602012-09-14 13:33:53 -04001043 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001044}
1045
1046bool TWPartition::Wipe_Data_Without_Wiping_Media() {
Dees_Troy38bd7602012-09-14 13:33:53 -04001047 char cmd[256];
1048
1049 // This handles wiping data on devices with "sdcard" in /data/media
1050 if (!Mount(true))
1051 return false;
1052
1053 ui_print("Wiping data without wiping /data/media ...\n");
Dees_Troy43d8b002012-09-17 16:00:01 -04001054 system("rm -f /data/*");
1055 system("rm -f /data/.*");
Dees_Troy38bd7602012-09-14 13:33:53 -04001056
1057 DIR* d;
1058 d = opendir("/data");
1059 if (d != NULL)
1060 {
1061 struct dirent* de;
1062 while ((de = readdir(d)) != NULL) {
1063 if (strcmp(de->d_name, "media") == 0) continue;
1064
1065 sprintf(cmd, "rm -fr /data/%s", de->d_name);
Dees_Troy43d8b002012-09-17 16:00:01 -04001066 system(cmd);
Dees_Troy38bd7602012-09-14 13:33:53 -04001067 }
1068 closedir(d);
1069 }
1070 ui_print("Done.\n");
1071 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001072}
1073
1074bool TWPartition::Backup_Tar(string backup_folder) {
Dees_Troy4a2a1262012-09-18 09:33:47 -04001075 char back_name[255], split_index[5];
1076 string Full_FileName, Split_FileName, Tar_Args, Command;
1077 int use_compression, index, backup_count;
1078 struct stat st;
1079 unsigned long long total_bsize = 0;
Dees_Troy43d8b002012-09-17 16:00:01 -04001080
1081 if (!Mount(true))
1082 return false;
1083
Dees_Troyb46a6842012-09-25 11:06:46 -04001084 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy43d8b002012-09-17 16:00:01 -04001085 ui_print("Backing up %s...\n", Display_Name.c_str());
1086
1087 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
1088 if (use_compression)
1089 Tar_Args = "-cz";
1090 else
1091 Tar_Args = "-c";
1092
1093 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1094 Backup_FileName = back_name;
1095
Dees_Troy43d8b002012-09-17 16:00:01 -04001096 if (Backup_Size > MAX_ARCHIVE_SIZE) {
1097 // This backup needs to be split into multiple archives
Dees_Troy4a2a1262012-09-18 09:33:47 -04001098 ui_print("Breaking backup file into multiple archives...\nGenerating file lists\n");
Dees_Troye58d5262012-09-21 12:27:57 -04001099 sprintf(back_name, "%s", Backup_Path.c_str());
Dees_Troy9df963c2012-09-26 08:58:12 -04001100 backup_count = MakeList::Make_File_List(back_name);
Dees_Troy4a2a1262012-09-18 09:33:47 -04001101 if (backup_count < 1) {
1102 LOGE("Error generating file list!\n");
1103 return false;
1104 }
1105 for (index=0; index<backup_count; index++) {
1106 sprintf(split_index, "%03i", index);
1107 Full_FileName = backup_folder + "/" + Backup_FileName + split_index;
1108 Command = "tar " + Tar_Args + " -f '" + Full_FileName + "' -T /tmp/list/filelist" + split_index;
1109 LOGI("Backup command: '%s'\n", Command.c_str());
1110 ui_print("Backup archive %i of %i...\n", (index + 1), backup_count);
1111 system(Command.c_str()); // sending backup command formed earlier above
1112
1113 if (stat(Full_FileName.c_str(), &st) != 0 || st.st_size == 0) {
1114 LOGE("File size is zero bytes. Aborting...\n\n"); // oh noes! file size is 0, abort! abort!
1115 return false;
1116 }
1117 total_bsize += st.st_size;
1118 }
1119 ui_print(" * Total size: %llu bytes.\n", total_bsize);
1120 system("cd /tmp && rm -rf list");
Dees_Troy43d8b002012-09-17 16:00:01 -04001121 } else {
Dees_Troy4a2a1262012-09-18 09:33:47 -04001122 Full_FileName = backup_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04001123 if (Has_Data_Media)
Dees_Troye58d5262012-09-21 12:27:57 -04001124 Command = "cd " + Backup_Path + " && tar " + Tar_Args + " ./ --exclude='media*' -f '" + Full_FileName + "'";
Dees_Troy43d8b002012-09-17 16:00:01 -04001125 else
Dees_Troye58d5262012-09-21 12:27:57 -04001126 Command = "cd " + Backup_Path + " && tar " + Tar_Args + " -f '" + Full_FileName + "' ./*";
Dees_Troy43d8b002012-09-17 16:00:01 -04001127 LOGI("Backup command: '%s'\n", Command.c_str());
1128 system(Command.c_str());
1129 }
1130 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001131}
1132
1133bool TWPartition::Backup_DD(string backup_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001134 char back_name[255];
1135 string Full_FileName, Command;
1136 int use_compression;
1137
Dees_Troyb46a6842012-09-25 11:06:46 -04001138 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy43d8b002012-09-17 16:00:01 -04001139 ui_print("Backing up %s...\n", Display_Name.c_str());
1140
1141 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1142 Backup_FileName = back_name;
1143
1144 Full_FileName = backup_folder + "/" + Backup_FileName;
1145
1146 Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'";
1147 LOGI("Backup command: '%s'\n", Command.c_str());
1148 system(Command.c_str());
1149 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001150}
1151
1152bool TWPartition::Backup_Dump_Image(string backup_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001153 char back_name[255];
1154 string Full_FileName, Command;
1155 int use_compression;
1156
Dees_Troyb46a6842012-09-25 11:06:46 -04001157 TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, "Backing Up");
Dees_Troy43d8b002012-09-17 16:00:01 -04001158 ui_print("Backing up %s...\n", Display_Name.c_str());
1159
1160 sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
1161 Backup_FileName = back_name;
1162
1163 Full_FileName = backup_folder + "/" + Backup_FileName;
1164
1165 Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
1166 LOGI("Backup command: '%s'\n", Command.c_str());
1167 system(Command.c_str());
1168 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001169}
1170
1171bool TWPartition::Restore_Tar(string restore_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001172 size_t first_period, second_period;
1173 string Restore_File_System, Full_FileName, Command;
Dees_Troy4a2a1262012-09-18 09:33:47 -04001174 int index = 0;
1175 char split_index[5];
Dees_Troy43d8b002012-09-17 16:00:01 -04001176
Dees_Troyb46a6842012-09-25 11:06:46 -04001177 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy43d8b002012-09-17 16:00:01 -04001178 LOGI("Restore filename is: %s\n", Backup_FileName.c_str());
1179
1180 // Parse backup filename to extract the file system before wiping
1181 first_period = Backup_FileName.find(".");
1182 if (first_period == string::npos) {
1183 LOGE("Unable to find file system (first period).\n");
1184 return false;
1185 }
1186 Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
1187 second_period = Restore_File_System.find(".");
1188 if (second_period == string::npos) {
1189 LOGE("Unable to find file system (second period).\n");
1190 return false;
1191 }
1192 Restore_File_System.resize(second_period);
1193 LOGI("Restore file system is: '%s'.\n", Restore_File_System.c_str());
1194 Current_File_System = Restore_File_System;
Dees_Troye58d5262012-09-21 12:27:57 -04001195 if (Has_Android_Secure) {
1196 ui_print("Wiping android secure...\n");
1197 if (!Wipe_AndSec())
1198 return false;
1199 } else if (!Wipe()) {
1200 ui_print("Wiping %s...\n", Display_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -04001201 return false;
Dees_Troye58d5262012-09-21 12:27:57 -04001202 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001203
1204 if (!Mount(true))
1205 return false;
1206
Dees_Troy43d8b002012-09-17 16:00:01 -04001207 ui_print("Restoring %s...\n", Display_Name.c_str());
Dees_Troy4a2a1262012-09-18 09:33:47 -04001208 Full_FileName = restore_folder + "/" + Backup_FileName;
Dees_Troy43d8b002012-09-17 16:00:01 -04001209 if (!TWFunc::Path_Exists(Full_FileName)) {
Dees_Troy4a2a1262012-09-18 09:33:47 -04001210 // Backup is multiple archives
1211 LOGI("Backup is multiple archives.\n");
1212 sprintf(split_index, "%03i", index);
1213 Full_FileName = restore_folder + "/" + Backup_FileName + split_index;
1214 while (TWFunc::Path_Exists(Full_FileName)) {
1215 ui_print("Restoring archive %i...\n", index + 1);
Dees_Troye58d5262012-09-21 12:27:57 -04001216 Command = "cd " + Backup_Path + " && tar -xf '" + Full_FileName + "'";
Dees_Troy4a2a1262012-09-18 09:33:47 -04001217 LOGI("Restore command: '%s'\n", Command.c_str());
1218 system(Command.c_str());
1219 index++;
1220 sprintf(split_index, "%03i", index);
1221 Full_FileName = restore_folder + "/" + Backup_FileName + split_index;
1222 }
1223 if (index == 0) {
1224 LOGE("Error locating restore file: '%s'\n", Full_FileName.c_str());
1225 return false;
1226 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001227 } else {
Dees_Troye58d5262012-09-21 12:27:57 -04001228 Command = "cd " + Backup_Path + " && tar -xf '" + Full_FileName + "'";
Dees_Troy43d8b002012-09-17 16:00:01 -04001229 LOGI("Restore command: '%s'\n", Command.c_str());
1230 system(Command.c_str());
1231 }
1232 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001233}
1234
1235bool TWPartition::Restore_DD(string restore_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001236 string Full_FileName, Command;
1237
Dees_Troyb46a6842012-09-25 11:06:46 -04001238 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy43d8b002012-09-17 16:00:01 -04001239 ui_print("Restoring %s...\n", Display_Name.c_str());
1240 Full_FileName = restore_folder + "/" + Backup_FileName;
1241 Command = "dd bs=4096 if='" + Full_FileName + "' of=" + Actual_Block_Device;
1242 LOGI("Restore command: '%s'\n", Command.c_str());
1243 system(Command.c_str());
1244 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001245}
1246
1247bool TWPartition::Restore_Flash_Image(string restore_folder) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001248 string Full_FileName, Command;
1249
Dees_Troyb46a6842012-09-25 11:06:46 -04001250 TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, "Restoring");
Dees_Troy43d8b002012-09-17 16:00:01 -04001251 ui_print("Restoring %s...\n", Display_Name.c_str());
1252 Full_FileName = restore_folder + "/" + Backup_FileName;
1253 // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes
1254 Command = "erase_image " + MTD_Name;
1255 LOGI("Erase command: '%s'\n", Command.c_str());
1256 system(Command.c_str());
1257 Command = "flash_image " + MTD_Name + " '" + Full_FileName + "'";
1258 LOGI("Restore command: '%s'\n", Command.c_str());
1259 system(Command.c_str());
1260 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001261}
Dees_Troy5bf43922012-09-07 16:07:55 -04001262
1263bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -04001264 bool ret = false;
1265
Dees_Troyab10ee22012-09-21 14:27:30 -04001266 if (!Can_Be_Mounted && !Is_Encrypted)
Dees_Troy5bf43922012-09-07 16:07:55 -04001267 return false;
1268
Dees_Troy38bd7602012-09-14 13:33:53 -04001269 if (Removable || Is_Encrypted) {
1270 if (!Mount(false))
1271 return true;
1272 } else if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -04001273 return false;
Dees_Troy51127312012-09-08 13:08:49 -04001274
1275 ret = Get_Size_Via_statfs(Display_Error);
1276 if (!ret || Size == 0)
1277 if (!Get_Size_Via_df(Display_Error))
1278 return false;
1279
Dees_Troy5bf43922012-09-07 16:07:55 -04001280 if (Has_Data_Media) {
1281 if (Mount(Display_Error)) {
Dees_Troy51127312012-09-08 13:08:49 -04001282 unsigned long long data_media_used, actual_data;
Dees_Troy43d8b002012-09-17 16:00:01 -04001283 Used = TWFunc::Get_Folder_Size("/data", Display_Error);
1284 data_media_used = TWFunc::Get_Folder_Size("/data/media", Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -04001285 actual_data = Used - data_media_used;
Dees_Troy5bf43922012-09-07 16:07:55 -04001286 Backup_Size = actual_data;
Dees_Troy51127312012-09-08 13:08:49 -04001287 int bak = (int)(Backup_Size / 1048576LLU);
1288 int total = (int)(Size / 1048576LLU);
1289 int us = (int)(Used / 1048576LLU);
1290 int fre = (int)(Free / 1048576LLU);
1291 int datmed = (int)(data_media_used / 1048576LLU);
1292 LOGI("Data backup size is %iMB, size: %iMB, used: %iMB, free: %iMB, in data/media: %iMB.\n", bak, total, us, fre, datmed);
Dees_Troy5bf43922012-09-07 16:07:55 -04001293 } else
1294 return false;
Dees_Troye58d5262012-09-21 12:27:57 -04001295 } else if (Has_Android_Secure) {
1296 if (Mount(Display_Error))
1297 Backup_Size = TWFunc::Get_Folder_Size(Backup_Path, Display_Error);
1298 else
1299 return false;
Dees_Troy5bf43922012-09-07 16:07:55 -04001300 }
1301 return true;
Dees_Troy51127312012-09-08 13:08:49 -04001302}
Dees_Troy38bd7602012-09-14 13:33:53 -04001303
1304void TWPartition::Find_Actual_Block_Device(void) {
1305 if (Is_Decrypted) {
1306 Actual_Block_Device = Decrypted_Block_Device;
Dees_Troy43d8b002012-09-17 16:00:01 -04001307 if (TWFunc::Path_Exists(Primary_Block_Device))
Dees_Troy38bd7602012-09-14 13:33:53 -04001308 Is_Present = true;
Dees_Troy43d8b002012-09-17 16:00:01 -04001309 } else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001310 Is_Present = true;
1311 Actual_Block_Device = Primary_Block_Device;
Dees_Troy43d8b002012-09-17 16:00:01 -04001312 } else if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001313 Flip_Block_Device();
1314 Actual_Block_Device = Primary_Block_Device;
1315 Is_Present = true;
1316 } else
1317 Is_Present = false;
1318}
1319
1320void TWPartition::Recreate_Media_Folder(void) {
1321 string Command;
1322
1323 if (!Mount(true)) {
1324 LOGE("Unable to recreate /data/media folder.\n");
Dees_Troyb46a6842012-09-25 11:06:46 -04001325 } else if (!TWFunc::Path_Exists("/data/media")) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001326 LOGI("Recreating /data/media folder.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -04001327 system("cd /data && mkdir media && chmod 755 media");
Dees_Troy38bd7602012-09-14 13:33:53 -04001328 Command = "umount " + Symlink_Mount_Point;
Dees_Troy43d8b002012-09-17 16:00:01 -04001329 system(Command.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001330 Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
Dees_Troy43d8b002012-09-17 16:00:01 -04001331 system(Command.c_str());
Dees_Troy38bd7602012-09-14 13:33:53 -04001332 }
Dees_Troy43d8b002012-09-17 16:00:01 -04001333}
Dees_Troye58d5262012-09-21 12:27:57 -04001334
1335void TWPartition::Recreate_AndSec_Folder(void) {
1336 string Command;
1337
1338 if (!Has_Android_Secure)
1339 return;
1340
1341 if (!Mount(true)) {
1342 LOGE("Unable to recreate android secure folder.\n");
1343 } else if (!TWFunc::Path_Exists(Symlink_Path)) {
1344 LOGI("Recreating android secure folder.\n");
1345 TWFunc::Recursive_Mkdir(Symlink_Path);
1346 Command = "umount " + Symlink_Mount_Point;
1347 system(Command.c_str());
1348 Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
1349 system(Command.c_str());
1350 }
1351}