blob: b30e3b729e7908cfc7f7274370b69845a1fae358 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001/* Partition Management classes 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>
28#include <unistd.h>
Dees_Troy5bf43922012-09-07 16:07:55 -040029#include <vector>
Dees_Troy51a0e822012-09-05 15:24:24 -040030
31#include "variables.h"
32#include "common.h"
33#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040034#include "data.hpp"
35
36#ifdef TW_INCLUDE_CRYPTO
37 #ifdef TW_INCLUDE_JB_CRYPTO
38 #include "crypto/jb/cryptfs.h"
39 #else
40 #include "crypto/ics/cryptfs.h"
41 #endif
42 #include "cutils/properties.h"
43#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040044
45int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -040046 FILE *fstabFile;
47 char fstab_line[MAX_FSTAB_LINE_LENGTH];
48
49 fstabFile = fopen(Fstab_Filename.c_str(), "rt");
50 if (fstabFile == NULL) {
51 LOGE("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str());
52 return false;
53 }
54
55 while (fgets(fstab_line, sizeof(fstab_line), fstabFile) != NULL) {
56 if (fstab_line[0] != '/')
57 continue;
58
59 TWPartition* partition = new TWPartition();
60 string line(fstab_line);
61 if (partition->Process_Fstab_Line(line, Display_Error)) {
62 Partitions.push_back(partition);
63 } else {
64 delete partition;
65 }
66 }
67 fclose(fstabFile);
68 if (!Write_Fstab()) {
69 if (Display_Error)
70 LOGE("Error creating fstab\n");
71 else
72 LOGI("Error creating fstab\n");
73 }
Dees_Troy51127312012-09-08 13:08:49 -040074 Update_System_Details();
Dees_Troy5bf43922012-09-07 16:07:55 -040075 return true;
76}
77
78int TWPartitionManager::Write_Fstab(void) {
79 FILE *fp;
80 std::vector<TWPartition*>::iterator iter;
81 string Line;
82
83 fp = fopen("/etc/fstab", "w");
84 if (fp == NULL) {
85 LOGI("Can not open /etc/fstab.\n");
86 return false;
87 }
88 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -040089 if ((*iter)->Can_Be_Mounted) {
Dees_Troy5bf43922012-09-07 16:07:55 -040090 if ((*iter)->Is_Decrypted)
91 Line = (*iter)->Decrypted_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
92 else
93 Line = (*iter)->Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
94 fputs(Line.c_str(), fp);
Dees_Troy51127312012-09-08 13:08:49 -040095 // Handle subpartition tracking
96 if ((*iter)->Is_SubPartition) {
97 TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
98 if (ParentPartition)
99 ParentPartition->Has_SubPartition = true;
100 else
101 LOGE("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
102 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400103 }
104 }
105 fclose(fp);
106 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400107}
108
109int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400110 std::vector<TWPartition*>::iterator iter;
111 int ret = false;
112 bool found = false;
Dees_Troy51127312012-09-08 13:08:49 -0400113 string Local_Path = Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400114
115 // Iterate through all partitions
116 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
117 if ((*iter)->Mount_Point == Local_Path) {
118 ret = (*iter)->Mount(Display_Error);
119 found = true;
Dees_Troy51127312012-09-08 13:08:49 -0400120 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400121 (*iter)->Mount(Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400122 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400123 }
124 if (found) {
125 return ret;
126 } else if (Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400127 LOGE("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400128 } else {
Dees_Troy51127312012-09-08 13:08:49 -0400129 LOGI("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400130 }
131 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400132}
133
134int TWPartitionManager::Mount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400135 TWPartition* Part = Find_Partition_By_Block(Block);
Dees_Troy5bf43922012-09-07 16:07:55 -0400136
Dees_Troy51127312012-09-08 13:08:49 -0400137 if (Part) {
138 if (Part->Has_SubPartition) {
139 std::vector<TWPartition*>::iterator subpart;
140
141 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
142 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
143 (*subpart)->Mount(Display_Error);
144 }
145 return Part->Mount(Display_Error);
146 } else
147 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400148 }
149 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400150 LOGE("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400151 else
Dees_Troy51127312012-09-08 13:08:49 -0400152 LOGI("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400153 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400154}
155
156int TWPartitionManager::Mount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400157 TWPartition* Part = Find_Partition_By_Name(Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400158
Dees_Troy51127312012-09-08 13:08:49 -0400159 if (Part) {
160 if (Part->Has_SubPartition) {
161 std::vector<TWPartition*>::iterator subpart;
162
163 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
164 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
165 (*subpart)->Mount(Display_Error);
166 }
167 return Part->Mount(Display_Error);
168 } else
169 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400170 }
171 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400172 LOGE("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400173 else
Dees_Troy51127312012-09-08 13:08:49 -0400174 LOGI("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400175 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400176}
177
178int TWPartitionManager::UnMount_By_Path(string Path, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400179 std::vector<TWPartition*>::iterator iter;
180 int ret = false;
181 bool found = false;
182 string Local_Path = Get_Root_Path(Path);
183
184 // Iterate through all partitions
185 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
186 if ((*iter)->Mount_Point == Local_Path) {
187 ret = (*iter)->UnMount(Display_Error);
188 found = true;
189 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
190 (*iter)->UnMount(Display_Error);
191 }
192 }
193 if (found) {
194 return ret;
195 } else if (Display_Error) {
196 LOGE("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
197 } else {
198 LOGI("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
199 }
200 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400201}
202
203int TWPartitionManager::UnMount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400204 TWPartition* Part = Find_Partition_By_Block(Block);
205
206 if (Part) {
207 if (Part->Has_SubPartition) {
208 std::vector<TWPartition*>::iterator subpart;
209
210 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
211 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
212 (*subpart)->UnMount(Display_Error);
213 }
214 return Part->UnMount(Display_Error);
215 } else
216 return Part->UnMount(Display_Error);
217 }
218 if (Display_Error)
219 LOGE("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
220 else
221 LOGI("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
222 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400223}
224
225int TWPartitionManager::UnMount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400226 TWPartition* Part = Find_Partition_By_Name(Name);
227
228 if (Part) {
229 if (Part->Has_SubPartition) {
230 std::vector<TWPartition*>::iterator subpart;
231
232 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
233 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
234 (*subpart)->UnMount(Display_Error);
235 }
236 return Part->UnMount(Display_Error);
237 } else
238 return Part->UnMount(Display_Error);
239 }
240 if (Display_Error)
241 LOGE("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
242 else
243 LOGI("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
244 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400245}
246
247int TWPartitionManager::Is_Mounted_By_Path(string Path) {
Dees_Troy51127312012-09-08 13:08:49 -0400248 TWPartition* Part = Find_Partition_By_Path(Path);
249
250 if (Part)
251 return Part->Is_Mounted();
252 else
253 LOGI("Is_Mounted: Unable to find partition for path '%s'\n", Path.c_str());
254 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400255}
256
257int TWPartitionManager::Is_Mounted_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400258 TWPartition* Part = Find_Partition_By_Block(Block);
259
260 if (Part)
261 return Part->Is_Mounted();
262 else
263 LOGI("Is_Mounted: Unable to find partition for block '%s'\n", Block.c_str());
264 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400265}
266
267int TWPartitionManager::Is_Mounted_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400268 TWPartition* Part = Find_Partition_By_Name(Name);
269
270 if (Part)
271 return Part->Is_Mounted();
272 else
273 LOGI("Is_Mounted: Unable to find partition for name '%s'\n", Name.c_str());
274 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400275}
276
Dees_Troy5bf43922012-09-07 16:07:55 -0400277int TWPartitionManager::Mount_Current_Storage(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400278 string current_storage_path = DataManager::GetCurrentStoragePath();
279
280 if (Mount_By_Path(current_storage_path, Display_Error)) {
281 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
282 if (FreeStorage)
283 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
284 return true;
285 }
286 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400287}
288
Dees_Troy5bf43922012-09-07 16:07:55 -0400289int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) {
290 return Mount_By_Path(DataManager::GetSettingsStoragePath(), Display_Error);
291}
292
293TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) {
294 std::vector<TWPartition*>::iterator iter;
Dees_Troy51127312012-09-08 13:08:49 -0400295 string Local_Path = Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400296
297 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -0400298 if ((*iter)->Mount_Point == Local_Path)
Dees_Troy5bf43922012-09-07 16:07:55 -0400299 return (*iter);
300 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400301 return NULL;
302}
303
Dees_Troy5bf43922012-09-07 16:07:55 -0400304TWPartition* TWPartitionManager::Find_Partition_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400305 std::vector<TWPartition*>::iterator iter;
306
307 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
308 if ((*iter)->Block_Device == Block || (*iter)->Alternate_Block_Device == Block || ((*iter)->Is_Decrypted && (*iter)->Decrypted_Block_Device == Block))
309 return (*iter);
310 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400311 return NULL;
Dees_Troy5bf43922012-09-07 16:07:55 -0400312}
313
314TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400315 std::vector<TWPartition*>::iterator iter;
316
317 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
318 if ((*iter)->Display_Name == Name)
319 return (*iter);
320 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400321 return NULL;
322}
Dees_Troy51a0e822012-09-05 15:24:24 -0400323
324int TWPartitionManager::Run_Backup(string Backup_Name) {
325 LOGI("STUB TWPartitionManager::Run_Backup, Backup_Name: '%s'\n", Backup_Name.c_str());
326 return 1;
327}
328
329int TWPartitionManager::Run_Restore(string Restore_Name) {
330 LOGI("STUB TWPartitionManager::Run_Restore, Restore_Name: '%s'\n", Restore_Name.c_str());
331 return 1;
332}
333
334void TWPartitionManager::Set_Restore_Files(string Restore_Name) {
335 LOGI("STUB TWPartitionManager::Set_Restore_Files\n");
336 return;
337}
338
339int TWPartitionManager::Wipe_By_Path(string Path) {
340 LOGI("STUB TWPartitionManager::Wipe_By_Path, Path: '%s'\n", Path.c_str());
341 return 1;
342}
343
344int TWPartitionManager::Wipe_By_Block(string Block) {
345 LOGI("STUB TWPartitionManager::Wipe_By_Block, Block: '%s'\n", Block.c_str());
346 return 1;
347}
348
349int TWPartitionManager::Wipe_By_Name(string Name) {
350 LOGI("STUB TWPartitionManager::Wipe_By_Name, Name: '%s'\n", Name.c_str());
351 return 1;
352}
353
354int TWPartitionManager::Factory_Reset(void) {
355 LOGI("STUB TWPartitionManager::Factory_Reset\n");
356 return 1;
357}
358
359void TWPartitionManager::Refresh_Sizes(void) {
Dees_Troy51127312012-09-08 13:08:49 -0400360 Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -0400361 return;
362}
363
364void TWPartitionManager::Update_System_Details(void) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400365 std::vector<TWPartition*>::iterator iter;
Dees_Troy51127312012-09-08 13:08:49 -0400366 int data_size = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -0400367
368 LOGI("Updating system details...\n");
369 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -0400370 if ((*iter)->Can_Be_Mounted) {
371 (*iter)->Update_Size(true);
372 if ((*iter)->Mount_Point == "/system") {
373 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
374 DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size);
375 } else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") {
376 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
377 } else if ((*iter)->Mount_Point == "/cache") {
378 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
379 DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size);
380 } else if ((*iter)->Mount_Point == "/sd-ext") {
381 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
382 DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size);
383 if ((*iter)->Backup_Size == 0) {
384 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0);
385 DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0);
386 } else
387 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1);
388 }
389 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400390 }
Dees_Troy51127312012-09-08 13:08:49 -0400391 DataManager::SetValue(TW_BACKUP_DATA_SIZE, data_size);
392 string current_storage_path = DataManager::GetCurrentStoragePath();
393 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
394 if (FreeStorage)
395 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
396 else
397 LOGI("Unable to find storage partition '%s'.\n", current_storage_path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400398 if (!Write_Fstab())
399 LOGE("Error creating fstab\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400400 return;
401}
402
403int TWPartitionManager::Decrypt_Device(string Password) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400404#ifdef TW_INCLUDE_CRYPTO
405 int ret_val, password_len;
406 char crypto_blkdev[255], cPassword[255];
407 size_t result;
408
409 property_set("ro.crypto.state", "encrypted");
410#ifdef TW_INCLUDE_JB_CRYPTO
411 // No extra flags needed
412#else
413 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
414 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
415 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
416 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
417 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
418 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
419#endif
420 strcpy(cPassword, Password.c_str());
421 if (cryptfs_check_passwd(cPassword) != 0) {
422 LOGE("Failed to decrypt data.\n");
423 return -1;
424 }
425 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
426 if (strcmp(crypto_blkdev, "error") == 0) {
427 LOGE("Error retrieving decrypted data block device.\n");
428 } else {
429 TWPartition* dat = Find_Partition_By_Path("/data");
430 if (dat != NULL) {
431 DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Block_Device);
432 DataManager::SetValue(TW_IS_DECRYPTED, 1);
433 dat->Is_Decrypted = true;
434 dat->Decrypted_Block_Device = crypto_blkdev;
435 LOGI("Data successfully decrypted, new block device: '%s'\n", crypto_blkdev);
436 // Sleep for a bit so that the device will be ready
437 sleep(1);
438 Update_System_Details();
439 } else
440 LOGE("Unable to locate data partition.\n");
441 }
442 return 0;
443#else
444 LOGE("No crypto support was compiled into this build.\n");
445 return -1;
446#endif
Dees_Troy51a0e822012-09-05 15:24:24 -0400447 return 1;
Dees_Troy51127312012-09-08 13:08:49 -0400448}
449
450string TWPartitionManager::Get_Root_Path(string Path) {
451 string Local_Path = Path;
452
453 // Make sure that we have a leading slash
454 if (Local_Path.substr(0, 1) != "/")
455 Local_Path = "/" + Local_Path;
456
457 // Trim the path to get the root path only
458 size_t position = Local_Path.find("/", 2);
459 if (position != string::npos) {
460 Local_Path.resize(position);
461 }
462 return Local_Path;
463}