blob: f3c79f7c2c620e24f11e40274537693974a4853d [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"
40extern "C" {
41 #include "extra-functions.h"
42 int __system(const char *command);
Dees_Troy5bf43922012-09-07 16:07:55 -040043}
Dees_Troy51a0e822012-09-05 15:24:24 -040044
45TWPartition::TWPartition(void) {
46 Can_Be_Mounted = false;
47 Can_Be_Wiped = false;
48 Wipe_During_Factory_Reset = false;
49 Wipe_Available_in_GUI = false;
50 Is_SubPartition = false;
51 SubPartition_Of = "";
52 Symlink_Path = "";
53 Symlink_Mount_Point = "";
54 Mount_Point = "";
55 Block_Device = "";
56 Alternate_Block_Device = "";
57 Removable = false;
58 Is_Present = false;
59 Length = 0;
60 Size = 0;
61 Used = 0;
62 Free = 0;
63 Backup_Size = 0;
64 Can_Be_Encrypted = false;
65 Is_Encrypted = false;
66 Is_Decrypted = false;
67 Decrypted_Block_Device = "";
68 Display_Name = "";
69 Backup_Name = "";
Dees_Troy63c8df72012-09-10 14:02:05 -040070 Backup_FileName = "";
Dees_Troy51a0e822012-09-05 15:24:24 -040071 Backup_Method = NONE;
72 Has_Data_Media = false;
73 Is_Storage = false;
74 Storage_Path = "";
75 Current_File_System = "";
76 Fstab_File_System = "";
77 Format_Block_Size = 0;
78}
79
80TWPartition::~TWPartition(void) {
81 // Do nothing
82}
83
Dees_Troy5bf43922012-09-07 16:07:55 -040084bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
85 char full_line[MAX_FSTAB_LINE_LENGTH], item[MAX_FSTAB_LINE_LENGTH];
86 int line_len = Line.size(), index = 0, item_index = 0;
87 char* ptr;
Dees_Troy51127312012-09-08 13:08:49 -040088 string Flags;
Dees_Troy5bf43922012-09-07 16:07:55 -040089
90 strncpy(full_line, Line.c_str(), line_len);
91
Dees_Troy51127312012-09-08 13:08:49 -040092 for (index = 0; index < line_len; index++) {
Dees_Troy5bf43922012-09-07 16:07:55 -040093 if (full_line[index] <= 32)
94 full_line[index] = '\0';
Dees_Troy5bf43922012-09-07 16:07:55 -040095 }
96 string mount_pt(full_line);
97 Mount_Point = mount_pt;
98 index = Mount_Point.size();
99 while (index < line_len) {
100 while (index < line_len && full_line[index] == '\0')
101 index++;
102 if (index >= line_len)
103 continue;
104 ptr = full_line + index;
105 if (item_index == 0) {
106 // File System
107 Fstab_File_System = ptr;
108 Current_File_System = ptr;
109 item_index++;
110 } else if (item_index == 1) {
111 // Primary Block Device
112 if (*ptr != '/') {
113 if (Display_Error)
114 LOGE("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
115 else
116 LOGI("Invalid block device on '%s', '%s', %i\n", Line.c_str(), ptr, index);
117 return 0;
118 }
119 Block_Device = ptr;
120 Find_Real_Block_Device(Block_Device, Display_Error);
121 item_index++;
122 } else if (item_index > 1) {
123 if (*ptr == '/') {
124 // Alternate Block Device
125 Alternate_Block_Device = ptr;
126 Find_Real_Block_Device(Alternate_Block_Device, Display_Error);
127 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
128 // Partition length
129 ptr += 7;
130 Length = atoi(ptr);
Dees_Troy51127312012-09-08 13:08:49 -0400131 } else if (strlen(ptr) > 6 && strncmp(ptr, "flags=", 6) == 0) {
132 // Custom flags, save for later so that new values aren't overwritten by defaults
133 ptr += 6;
134 Flags = ptr;
Dees_Troy5bf43922012-09-07 16:07:55 -0400135 } else {
136 // Unhandled data
137 LOGI("Unhandled fstab information: '%s', %i\n", ptr, index);
138 }
139 }
140 while (index < line_len && full_line[index] != '\0')
141 index++;
142 }
143
144 if (!Is_File_System(Fstab_File_System) && !Is_Image(Fstab_File_System)) {
145 if (Display_Error)
146 LOGE("Unknown File System: '%s'\n", Fstab_File_System.c_str());
147 else
148 LOGI("Unknown File System: '%s'\n", Fstab_File_System.c_str());
149 return 0;
150 } else if (Is_File_System(Fstab_File_System)) {
151 Setup_File_System(Display_Error);
152 if (Mount_Point == "/system") {
153 Display_Name = "System";
154 Wipe_Available_in_GUI = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400155 } else if (Mount_Point == "/data") {
156 Display_Name = "Data";
157 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400158 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400159#ifdef RECOVERY_SDCARD_ON_DATA
160 Has_Data_Media = true;
Dees_Troy51127312012-09-08 13:08:49 -0400161 Is_Storage = true;
162 Storage_Path = "/data/media";
Dees_Troy657c3092012-09-10 20:32:10 -0400163 if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
164 Make_Dir("/emmc", Display_Error);
165 Symlink_Path = "/data/media";
166 Symlink_Mount_Point = "/emmc";
167 } else {
168 Make_Dir("/sdcard", Display_Error);
169 Symlink_Path = "/data/media";
170 Symlink_Mount_Point = "/sdcard";
171 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400172#endif
173#ifdef TW_INCLUDE_CRYPTO
174 Can_Be_Encrypted = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400175 char crypto_blkdev[255];
176 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
177 if (strcmp(crypto_blkdev, "error") != 0) {
178 DataManager::SetValue(TW_DATA_BLK_DEVICE, Block_Device);
179 DataManager::SetValue(TW_IS_DECRYPTED, 1);
180 Is_Encrypted = true;
181 Is_Decrypted = true;
182 Decrypted_Block_Device = crypto_blkdev;
183 LOGI("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
184 } else if (!Mount(false)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400185 Is_Encrypted = true;
186 Is_Decrypted = false;
187 DataManager::SetValue(TW_IS_ENCRYPTED, 1);
188 DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
189 DataManager::SetValue("tw_crypto_display", "");
Dees_Troy51127312012-09-08 13:08:49 -0400190 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400191#endif
Dees_Troy5bf43922012-09-07 16:07:55 -0400192 } else if (Mount_Point == "/cache") {
193 Display_Name = "Cache";
194 Wipe_Available_in_GUI = true;
Dees_Troy51127312012-09-08 13:08:49 -0400195 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400196 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400197 } else if (Mount_Point == "/datadata") {
Dees_Troy51127312012-09-08 13:08:49 -0400198 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400199 Display_Name = "DataData";
200 Is_SubPartition = true;
201 SubPartition_Of = "/data";
Dees_Troy5bf43922012-09-07 16:07:55 -0400202 DataManager::SetValue(TW_HAS_DATADATA, 1);
203 } else if (Mount_Point == "/sd-ext") {
Dees_Troy51127312012-09-08 13:08:49 -0400204 Wipe_During_Factory_Reset = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400205 Display_Name = "SD-Ext";
206 Wipe_Available_in_GUI = true;
Dees_Troy5bf43922012-09-07 16:07:55 -0400207 } else
208 Update_Size(Display_Error);
209 } else if (Is_Image(Fstab_File_System)) {
210 Setup_Image(Display_Error);
211 if (Mount_Point == "/boot") {
212 int backup_display_size = (int)(Backup_Size / 1048576LLU);
213 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
214 if (Backup_Size == 0) {
215 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 0);
216 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
217 } else
218 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 1);
219 } else if (Mount_Point == "/recovery") {
220 int backup_display_size = (int)(Backup_Size / 1048576LLU);
221 DataManager::SetValue(TW_BACKUP_RECOVERY_SIZE, backup_display_size);
222 if (Backup_Size == 0) {
223 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 0);
224 DataManager::SetValue(TW_BACKUP_RECOVERY_VAR, 0);
225 } else
226 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 1);
227 }
228 }
229
Dees_Troy51127312012-09-08 13:08:49 -0400230 // Process any custom flags
231 if (Flags.size() > 0)
232 Process_Flags(Flags, Display_Error);
233
234 return true;
235}
236
237bool TWPartition::Process_Flags(string Flags, bool Display_Error) {
238 char flags[MAX_FSTAB_LINE_LENGTH];
239 int flags_len, index = 0;
240 char* ptr;
241
242 strcpy(flags, Flags.c_str());
243 flags_len = Flags.size();
244 for (index = 0; index < flags_len; index++) {
245 if (flags[index] == ';')
246 flags[index] = '\0';
247 }
248
249 index = 0;
250 while (index < flags_len) {
251 while (index < flags_len && flags[index] == '\0')
252 index++;
253 if (index >= flags_len)
254 continue;
255 ptr = flags + index;
256 if (strcmp(ptr, "removable") == 0) {
257 Removable = true;
258 } else if (strcmp(ptr, "storage") == 0) {
259 Is_Storage = true;
Dees_Troy63c8df72012-09-10 14:02:05 -0400260 } else if (strcmp(ptr, "canbewiped") == 0) {
261 Can_Be_Wiped = true;
262 } else if (strcmp(ptr, "wipeingui") == 0) {
263 Can_Be_Wiped = true;
264 Wipe_Available_in_GUI = true;
265 } else if (strcmp(ptr, "wipeduringfactoryreset") == 0) {
266 Can_Be_Wiped = true;
267 Wipe_Available_in_GUI = true;
268 Wipe_During_Factory_Reset = true;
Dees_Troy51127312012-09-08 13:08:49 -0400269 } else if (strlen(ptr) > 15 && strncmp(ptr, "subpartitionof=", 15) == 0) {
270 ptr += 13;
271 Is_SubPartition = true;
272 SubPartition_Of = ptr;
273 } else if (strlen(ptr) > 8 && strncmp(ptr, "symlink=", 8) == 0) {
274 ptr += 8;
275 Symlink_Path = ptr;
276 } else if (strlen(ptr) > 8 && strncmp(ptr, "display=", 8) == 0) {
277 ptr += 8;
278 Display_Name = ptr;
279 } else if (strlen(ptr) > 10 && strncmp(ptr, "blocksize=", 10) == 0) {
280 ptr += 10;
281 Format_Block_Size = atoi(ptr);
282 } else if (strlen(ptr) > 7 && strncmp(ptr, "length=", 7) == 0) {
283 ptr += 7;
284 Length = atoi(ptr);
285 } else {
286 if (Display_Error)
287 LOGE("Unhandled flag: '%s'\n", ptr);
288 else
289 LOGI("Unhandled flag: '%s'\n", ptr);
290 }
291 while (index < flags_len && flags[index] != '\0')
292 index++;
293 }
294 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400295}
296
Dees_Troy5bf43922012-09-07 16:07:55 -0400297bool TWPartition::Is_File_System(string File_System) {
298 if (File_System == "ext2" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400299 File_System == "ext3" ||
Dees_Troy5bf43922012-09-07 16:07:55 -0400300 File_System == "ext4" ||
301 File_System == "vfat" ||
302 File_System == "ntfs" ||
303 File_System == "yaffs2" ||
304 File_System == "auto")
305 return true;
306 else
307 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400308}
309
Dees_Troy5bf43922012-09-07 16:07:55 -0400310bool TWPartition::Is_Image(string File_System) {
311 if (File_System == "emmc" ||
Dees_Troy63c8df72012-09-10 14:02:05 -0400312 File_System == "mtd")
Dees_Troy5bf43922012-09-07 16:07:55 -0400313 return true;
314 else
315 return false;
316}
317
Dees_Troy51127312012-09-08 13:08:49 -0400318bool TWPartition::Make_Dir(string Path, bool Display_Error) {
319 if (!Path_Exists(Path)) {
320 if (mkdir(Path.c_str(), 0777) == -1) {
321 if (Display_Error)
322 LOGE("Can not create '%s' folder.\n", Path.c_str());
323 else
324 LOGI("Can not create '%s' folder.\n", Path.c_str());
325 return false;
326 } else {
327 LOGI("Created '%s' folder.\n", Path.c_str());
328 return true;
329 }
330 }
331 return true;
332}
333
Dees_Troy5bf43922012-09-07 16:07:55 -0400334void TWPartition::Setup_File_System(bool Display_Error) {
335 struct statfs st;
336
337 Can_Be_Mounted = true;
338 Can_Be_Wiped = true;
339
340 // Check to see if the block device exists
341 if (Path_Exists(Block_Device)) {
342 Is_Present = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400343 } else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400344 Flip_Block_Device();
345 Is_Present = true;
346 }
347 // Make the mount point folder if it doesn't exist
Dees_Troy51127312012-09-08 13:08:49 -0400348 Make_Dir(Mount_Point, Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400349 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
350 Backup_Name = Display_Name;
351 Backup_Method = FILES;
352}
353
354void TWPartition::Setup_Image(bool Display_Error) {
355 if (Path_Exists(Block_Device)) {
356 Is_Present = true;
Dees_Troy657c3092012-09-10 20:32:10 -0400357 } else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400358 Flip_Block_Device();
359 Is_Present = true;
360 }
361 Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1);
362 Backup_Name = Display_Name;
363 if (Fstab_File_System == "emmc")
364 Backup_Method = DD;
365 else if (Fstab_File_System == "mtd")
366 Backup_Method = FLASH_UTILS;
367 else
368 LOGI("Unhandled file system '%s' on image '%s'\n", Fstab_File_System.c_str(), Display_Name.c_str());
369 if (Find_Partition_Size()) {
370 Used = Size;
371 Backup_Size = Size;
Dees_Troy51a0e822012-09-05 15:24:24 -0400372 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400373 if (Display_Error)
374 LOGE("Unable to find parition size for '%s'\n", Block_Device.c_str());
375 else
376 LOGI("Unable to find parition size for '%s'\n", Block_Device.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400377 }
378}
379
Dees_Troy5bf43922012-09-07 16:07:55 -0400380void TWPartition::Find_Real_Block_Device(string& Block, bool Display_Error) {
381 char device[512], realDevice[512];
382
383 strcpy(device, Block.c_str());
384 memset(realDevice, 0, sizeof(realDevice));
385 while (readlink(device, realDevice, sizeof(realDevice)) > 0)
386 {
387 strcpy(device, realDevice);
388 memset(realDevice, 0, sizeof(realDevice));
389 }
390
391 if (device[0] != '/') {
392 if (Display_Error)
393 LOGE("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
394 else
395 LOGI("Invalid symlink path '%s' found on block device '%s'\n", device, Block.c_str());
396 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400397 } else {
Dees_Troy5bf43922012-09-07 16:07:55 -0400398 Block = device;
399 return;
400 }
401}
402
Dees_Troy51127312012-09-08 13:08:49 -0400403bool TWPartition::Get_Size_Via_statfs(bool Display_Error) {
404 struct statfs st;
405 string Local_Path = Mount_Point + "/.";
406
407 if (!Mount(Display_Error))
408 return false;
409
410 if (statfs(Local_Path.c_str(), &st) != 0) {
411 if (!Removable) {
412 if (Display_Error)
413 LOGE("Unable to statfs '%s'\n", Local_Path.c_str());
414 else
415 LOGI("Unable to statfs '%s'\n", Local_Path.c_str());
416 }
417 return false;
418 }
419 Size = (st.f_blocks * st.f_bsize);
420 Used = ((st.f_blocks - st.f_bfree) * st.f_bsize);
421 Free = (st.f_bfree * st.f_bsize);
422 Backup_Size = Used;
423 return true;
424}
425
426bool TWPartition::Get_Size_Via_df(bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400427 FILE* fp;
428 char command[255], line[512];
429 int include_block = 1;
430 unsigned int min_len;
431
432 if (!Mount(Display_Error))
433 return false;
434
435 min_len = Block_Device.size() + 2;
Dees_Troy51127312012-09-08 13:08:49 -0400436 sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
437 __system(command);
438 fp = fopen("/tmp/dfoutput.txt", "rt");
439 if (fp == NULL) {
440 LOGI("Unable to open /tmp/dfoutput.txt.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400441 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400442 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400443
444 while (fgets(line, sizeof(line), fp) != NULL)
445 {
446 unsigned long blocks, used, available;
447 char device[64];
448 char tmpString[64];
449
450 if (strncmp(line, "Filesystem", 10) == 0)
451 continue;
452 if (strlen(line) < min_len) {
453 include_block = 0;
454 continue;
455 }
456 if (include_block) {
457 sscanf(line, "%s %lu %lu %lu", device, &blocks, &used, &available);
458 } else {
459 // The device block string is so long that the df information is on the next line
460 int space_count = 0;
461 while (tmpString[space_count] == 32)
462 space_count++;
463 sscanf(line + space_count, "%lu %lu %lu", &blocks, &used, &available);
464 }
465
466 // Adjust block size to byte size
467 Size = blocks * 1024ULL;
468 Used = used * 1024ULL;
469 Free = available * 1024ULL;
470 Backup_Size = Used;
471 }
472 fclose(fp);
473 return true;
474}
475
Dees_Troy51127312012-09-08 13:08:49 -0400476unsigned long long TWPartition::Get_Folder_Size(string Path, bool Display_Error) {
477 DIR* d;
478 struct dirent* de;
479 struct stat st;
480 char path2[1024], filename[1024];
481 unsigned long long dusize = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -0400482
Dees_Troy51127312012-09-08 13:08:49 -0400483 // Make a copy of path in case the data in the pointer gets overwritten later
484 strcpy(path2, Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400485
Dees_Troy51127312012-09-08 13:08:49 -0400486 d = opendir(path2);
487 if (d == NULL)
488 {
489 LOGE("error opening '%s'\n", path2);
490 return 0;
491 }
492
493 while ((de = readdir(d)) != NULL)
494 {
495 if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
496 {
497 strcpy(filename, path2);
498 strcat(filename, "/");
499 strcat(filename, de->d_name);
500 dusize += Get_Folder_Size(filename, Display_Error);
501 }
502 else if (de->d_type == DT_REG)
503 {
504 strcpy(filename, path2);
505 strcat(filename, "/");
506 strcat(filename, de->d_name);
507 stat(filename, &st);
508 dusize += (unsigned long long)(st.st_size);
509 }
510 }
511 closedir(d);
Dees_Troy5bf43922012-09-07 16:07:55 -0400512
Dees_Troy63c8df72012-09-10 14:02:05 -0400513 return dusize;
Dees_Troy5bf43922012-09-07 16:07:55 -0400514}
515
516bool TWPartition::Find_Partition_Size(void) {
517 FILE* fp;
518 char line[512];
519 string tmpdevice;
520
521 // In this case, we'll first get the partitions we care about (with labels)
522 fp = fopen("/proc/partitions", "rt");
523 if (fp == NULL)
524 return false;
525
526 while (fgets(line, sizeof(line), fp) != NULL)
527 {
528 unsigned long major, minor, blocks;
529 char device[512];
530 char tmpString[64];
531
Dees_Troy63c8df72012-09-10 14:02:05 -0400532 if (strlen(line) < 7 || line[0] == 'm') continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400533 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
534
535 tmpdevice = "/dev/block/";
536 tmpdevice += device;
537 if (tmpdevice == Block_Device || tmpdevice == Alternate_Block_Device) {
538 // Adjust block size to byte size
539 Size = blocks * 1024ULL;
540 fclose(fp);
541 return true;
542 }
543 }
544 fclose(fp);
545 return false;
546}
547
548bool TWPartition::Path_Exists(string Path) {
549 // Check to see if the Path exists
550 struct statfs st;
551
552 if (statfs(Path.c_str(), &st) != 0)
553 return false;
554 else
555 return true;
556}
557
558void TWPartition::Flip_Block_Device(void) {
559 string temp;
560
561 temp = Alternate_Block_Device;
562 Block_Device = Alternate_Block_Device;
563 Alternate_Block_Device = temp;
564}
565
566bool TWPartition::Is_Mounted(void) {
567 if (!Can_Be_Mounted)
568 return false;
569
570 struct stat st1, st2;
571 string test_path;
572
573 // Check to see if the mount point directory exists
574 test_path = Mount_Point + "/.";
575 if (stat(test_path.c_str(), &st1) != 0) return false;
576
577 // Check to see if the directory above the mount point exists
578 test_path = Mount_Point + "/../.";
579 if (stat(test_path.c_str(), &st2) != 0) return false;
580
581 // Compare the device IDs -- if they match then we're (probably) using tmpfs instead of an actual device
582 int ret = (st1.st_dev != st2.st_dev) ? true : false;
583
584 return ret;
585}
586
587bool TWPartition::Mount(bool Display_Error) {
588 if (Is_Mounted()) {
589 return true;
590 } else if (!Can_Be_Mounted) {
591 return false;
592 }
Dees_Troy51127312012-09-08 13:08:49 -0400593 if (Removable)
594 Check_FS_Type();
Dees_Troy5bf43922012-09-07 16:07:55 -0400595 if (Is_Decrypted) {
596 if (mount(Decrypted_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
597 Check_FS_Type();
598 if (mount(Decrypted_Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
599 if (Display_Error)
600 LOGE("Unable to mount decrypted block device '%s' to '%s'\n", Decrypted_Block_Device.c_str(), Mount_Point.c_str());
601 else
602 LOGI("Unable to mount decrypted block device '%s' to '%s'\n", Decrypted_Block_Device.c_str(), Mount_Point.c_str());
603 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400604 } else {
605 if (Removable)
606 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400607 return true;
Dees_Troy51127312012-09-08 13:08:49 -0400608 }
609 } else {
610 if (Removable)
611 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400612 return true;
Dees_Troy51127312012-09-08 13:08:49 -0400613 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400614 }
615 if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
616 Check_FS_Type();
617 if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
Dees_Troy657c3092012-09-10 20:32:10 -0400618 if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400619 Flip_Block_Device();
620 Check_FS_Type();
621 if (mount(Block_Device.c_str(), Mount_Point.c_str(), Current_File_System.c_str(), 0, NULL) != 0) {
622 if (Display_Error)
623 LOGE("Unable to mount '%s'\n", Mount_Point.c_str());
624 else
625 LOGI("Unable to mount '%s'\n", Mount_Point.c_str());
626 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400627 } else {
628 if (Removable)
629 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400630 return true;
Dees_Troy51127312012-09-08 13:08:49 -0400631 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400632 } else
633 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400634 } else {
635 if (Removable)
636 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400637 return true;
Dees_Troy51127312012-09-08 13:08:49 -0400638 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400639 }
Dees_Troy51127312012-09-08 13:08:49 -0400640 if (Removable)
641 Update_Size(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400642 return true;
643}
644
645bool TWPartition::UnMount(bool Display_Error) {
646 if (Is_Mounted()) {
647 int never_unmount_system;
648
649 DataManager::GetValue(TW_DONT_UNMOUNT_SYSTEM, never_unmount_system);
650 if (never_unmount_system == 1 && Mount_Point == "/system")
651 return true; // Never unmount system if you're not supposed to unmount it
652
653 if (umount(Mount_Point.c_str()) != 0) {
654 if (Display_Error)
655 LOGE("Unable to unmount '%s'\n", Mount_Point.c_str());
656 else
657 LOGI("Unable to unmount '%s'\n", Mount_Point.c_str());
658 return false;
659 } else
660 return true;
661 } else {
662 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400663 }
664}
665
666bool TWPartition::Wipe() {
667 LOGI("STUB TWPartition::Wipe\n");
668 return 1;
669}
670
671bool TWPartition::Backup(string backup_folder) {
672 LOGI("STUB TWPartition::Backup, backup_folder: '%s'\n", backup_folder.c_str());
673 return 1;
674}
675
676bool TWPartition::Restore(string restore_folder) {
677 LOGI("STUB TWPartition::Restore, restore_folder: '%s'\n", restore_folder.c_str());
678 return 1;
679}
680
681string TWPartition::Backup_Method_By_Name() {
682 LOGI("STUB TWPartition::Backup_Method_By_Name\n");
683 return "STUB";
684}
685
686bool TWPartition::Decrypt(string Password) {
687 LOGI("STUB TWPartition::Decrypt, password: '%s'\n", Password.c_str());
688 return 1;
689}
690
691bool TWPartition::Wipe_Encryption() {
692 LOGI("STUB TWPartition::Wipe_Encryption\n");
693 return 1;
694}
695
696void TWPartition::Check_FS_Type() {
Dees_Troy5bf43922012-09-07 16:07:55 -0400697 FILE *fp;
698 string blkCommand;
699 char blkOutput[255];
700 char* blk;
701 char* arg;
702 char* ptr;
703
704 if (Fstab_File_System == "yaffs2" || Fstab_File_System == "mtd")
705 return; // Running blkid on some mtd devices causes a massive crash
706
707 if (Is_Decrypted)
Dees_Troy51127312012-09-08 13:08:49 -0400708 blkCommand = "blkid " + Decrypted_Block_Device + " > /tmp/blkidoutput.txt";
Dees_Troy5bf43922012-09-07 16:07:55 -0400709 else
Dees_Troy51127312012-09-08 13:08:49 -0400710 blkCommand = "blkid " + Block_Device + " > /tmp/blkidoutput.txt";
711
712 __system(blkCommand.c_str());
713 fp = fopen("/tmp/blkidoutput.txt", "rt");
Dees_Troy5bf43922012-09-07 16:07:55 -0400714 while (fgets(blkOutput, sizeof(blkOutput), fp) != NULL)
715 {
716 blk = blkOutput;
717 ptr = blkOutput;
Dees_Troy63c8df72012-09-10 14:02:05 -0400718 while (*ptr > 32 && *ptr != ':') ptr++;
719 if (*ptr == 0) continue;
Dees_Troy5bf43922012-09-07 16:07:55 -0400720 *ptr = 0;
721
722 // Increment by two, but verify that we don't hit a NULL
723 ptr++;
Dees_Troy63c8df72012-09-10 14:02:05 -0400724 if (*ptr != 0) ptr++;
Dees_Troy5bf43922012-09-07 16:07:55 -0400725
726 // Now, find the TYPE field
727 while (1)
728 {
729 arg = ptr;
Dees_Troy63c8df72012-09-10 14:02:05 -0400730 while (*ptr > 32) ptr++;
Dees_Troy5bf43922012-09-07 16:07:55 -0400731 if (*ptr != 0)
732 {
733 *ptr = 0;
734 ptr++;
735 }
736
737 if (strlen(arg) > 6)
738 {
739 if (memcmp(arg, "TYPE=\"", 6) == 0) break;
740 }
741
742 if (*ptr == 0)
743 {
744 arg = NULL;
745 break;
746 }
747 }
748
749 if (arg && strlen(arg) > 7)
750 {
751 arg += 6; // Skip the TYPE=" portion
752 arg[strlen(arg)-1] = '\0'; // Drop the tail quote
753 }
754 else
755 continue;
756
Dees_Troy63c8df72012-09-10 14:02:05 -0400757 if (strcmp(Current_File_System.c_str(), arg) != 0) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400758 LOGI("'%s' was '%s' now set to '%s'\n", Mount_Point.c_str(), Current_File_System.c_str(), arg);
759 Current_File_System = arg;
760 }
761 }
762 __pclose(fp);
Dees_Troy51a0e822012-09-05 15:24:24 -0400763 return;
764}
765
766bool TWPartition::Wipe_EXT23() {
767 LOGI("STUB TWPartition::Wipe_EXT23\n");
768 return 1;
769}
770
771bool TWPartition::Wipe_EXT4() {
772 LOGI("STUB TWPartition::Wipe_EXT4\n");
773 return 1;
774}
775
776bool TWPartition::Wipe_FAT() {
777 LOGI("STUB TWPartition::Wipe_FAT\n");
778 return 1;
779}
780
781bool TWPartition::Wipe_YAFFS2() {
782 LOGI("STUB TWPartition::Wipe_YAFFS2\n");
783 return 1;
784}
785
786bool TWPartition::Wipe_RMRF() {
787 LOGI("STUB TWPartition::Wipe_RMRF\n");
788 return 1;
789}
790
791bool TWPartition::Wipe_Data_Without_Wiping_Media() {
792 LOGI("STUB TWPartition::Wipe_Data_Without_Wiping_Media\n");
793 return 1;
794}
795
796bool TWPartition::Backup_Tar(string backup_folder) {
797 LOGI("STUB TWPartition::Backup_Tar, backup_folder: '%s'\n", backup_folder.c_str());
798 return 1;
799}
800
801bool TWPartition::Backup_DD(string backup_folder) {
802 LOGI("STUB TWPartition::Backup_DD, backup_folder: '%s'\n", backup_folder.c_str());
803 return 1;
804}
805
806bool TWPartition::Backup_Dump_Image(string backup_folder) {
807 LOGI("STUB TWPartition::Backup_Dump_Image, backup_folder: '%s'\n", backup_folder.c_str());
808 return 1;
809}
810
811bool TWPartition::Restore_Tar(string restore_folder) {
812 LOGI("STUB TWPartition::Restore_Tar, backup_folder: '%s'\n", restore_folder.c_str());
813 return 1;
814}
815
816bool TWPartition::Restore_DD(string restore_folder) {
817 LOGI("STUB TWPartition::Restore_DD, backup_folder: '%s'\n", restore_folder.c_str());
818 return 1;
819}
820
821bool TWPartition::Restore_Flash_Image(string restore_folder) {
822 LOGI("STUB TWPartition::Restore_Flash_Image, backup_folder: '%s'\n", restore_folder.c_str());
823 return 1;
824}
Dees_Troy5bf43922012-09-07 16:07:55 -0400825
826bool TWPartition::Update_Size(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400827 bool ret = false;
828
Dees_Troy5bf43922012-09-07 16:07:55 -0400829 if (!Can_Be_Mounted)
830 return false;
831
Dees_Troy51127312012-09-08 13:08:49 -0400832 if (!Mount(Display_Error))
Dees_Troy5bf43922012-09-07 16:07:55 -0400833 return false;
Dees_Troy51127312012-09-08 13:08:49 -0400834
835 ret = Get_Size_Via_statfs(Display_Error);
836 if (!ret || Size == 0)
837 if (!Get_Size_Via_df(Display_Error))
838 return false;
839
Dees_Troy5bf43922012-09-07 16:07:55 -0400840 if (Has_Data_Media) {
841 if (Mount(Display_Error)) {
Dees_Troy51127312012-09-08 13:08:49 -0400842 unsigned long long data_media_used, actual_data;
843 data_media_used = Get_Folder_Size("/data/media", Display_Error);
844 actual_data = Used - data_media_used;
Dees_Troy5bf43922012-09-07 16:07:55 -0400845 Backup_Size = actual_data;
Dees_Troy51127312012-09-08 13:08:49 -0400846 int bak = (int)(Backup_Size / 1048576LLU);
847 int total = (int)(Size / 1048576LLU);
848 int us = (int)(Used / 1048576LLU);
849 int fre = (int)(Free / 1048576LLU);
850 int datmed = (int)(data_media_used / 1048576LLU);
851 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 -0400852 } else
853 return false;
854 }
855 return true;
Dees_Troy51127312012-09-08 13:08:49 -0400856}