blob: f40b35eeb32b44ddf0c92341c428532db4749153 [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_Troy63c8df72012-09-10 14:02:05 -040030#include <dirent.h>
31#include <time.h>
Dees_Troy8170a922012-09-18 15:40:25 -040032#include <errno.h>
33#include <fcntl.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050034#include <iostream>
35#include <iomanip>
Dees_Troy51a0e822012-09-05 15:24:24 -040036#include "variables.h"
37#include "common.h"
Dees_Troy093b7642012-09-21 15:59:38 -040038#include "ui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040039#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040040#include "data.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040041#include "twrp-functions.hpp"
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -040042#include "fixPermissions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050043#include "twrpDigest.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040044
Dees_Troy5bf43922012-09-07 16:07:55 -040045#ifdef TW_INCLUDE_CRYPTO
46 #ifdef TW_INCLUDE_JB_CRYPTO
47 #include "crypto/jb/cryptfs.h"
48 #else
49 #include "crypto/ics/cryptfs.h"
50 #endif
51 #include "cutils/properties.h"
52#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040053
Dees_Troy093b7642012-09-21 15:59:38 -040054extern RecoveryUI* ui;
55
Dees_Troy51a0e822012-09-05 15:24:24 -040056int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -040057 FILE *fstabFile;
58 char fstab_line[MAX_FSTAB_LINE_LENGTH];
Dees_Troya13d74f2013-03-24 08:54:55 -050059 bool Found_Settings_Storage = false;
Dees_Troy5bf43922012-09-07 16:07:55 -040060
61 fstabFile = fopen(Fstab_Filename.c_str(), "rt");
62 if (fstabFile == NULL) {
63 LOGE("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str());
64 return false;
65 }
66
67 while (fgets(fstab_line, sizeof(fstab_line), fstabFile) != NULL) {
68 if (fstab_line[0] != '/')
69 continue;
70
Dees_Troy2a923582012-09-20 12:13:34 -040071 if (fstab_line[strlen(fstab_line) - 1] != '\n')
72 fstab_line[strlen(fstab_line)] = '\n';
73
Dees_Troy5bf43922012-09-07 16:07:55 -040074 TWPartition* partition = new TWPartition();
Dees_Troy2a923582012-09-20 12:13:34 -040075 string line = fstab_line;
Dees_Troyab10ee22012-09-21 14:27:30 -040076 memset(fstab_line, 0, sizeof(fstab_line));
Dees_Troy2a923582012-09-20 12:13:34 -040077
Dees_Troy5bf43922012-09-07 16:07:55 -040078 if (partition->Process_Fstab_Line(line, Display_Error)) {
Dees_Troya13d74f2013-03-24 08:54:55 -050079 if (!Found_Settings_Storage && partition->Is_Settings_Storage) {
80 Found_Settings_Storage = true;
81 Partitions.push_back(partition);
82 DataManager::SetValue("tw_settings_path", partition->Storage_Path);
83 DataManager::SetValue("tw_storage_path", partition->Storage_Path);
84 LOGI("Settings storage is '%s'\n", partition->Storage_Path.c_str());
85 } else {
86 partition->Is_Settings_Storage = false;
87 Partitions.push_back(partition);
88 }
Dees_Troy5bf43922012-09-07 16:07:55 -040089 } else {
90 delete partition;
91 }
92 }
93 fclose(fstabFile);
Dees_Troya13d74f2013-03-24 08:54:55 -050094 if (!Found_Settings_Storage) {
95 std::vector<TWPartition*>::iterator iter;
96 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
97 if ((*iter)->Is_Storage) {
98 (*iter)->Is_Settings_Storage = true;
99 Found_Settings_Storage = true;
100 DataManager::SetValue("tw_settings_path", (*iter)->Storage_Path);
101 DataManager::SetValue("tw_storage_path", (*iter)->Storage_Path);
102 LOGI("Settings storage is '%s'\n", (*iter)->Storage_Path.c_str());
103 break;
104 }
105 }
106 if (!Found_Settings_Storage)
107 LOGE("Unable to locate storage partition for storing settings file.\n");
108 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400109 if (!Write_Fstab()) {
110 if (Display_Error)
111 LOGE("Error creating fstab\n");
112 else
113 LOGI("Error creating fstab\n");
114 }
Dees_Troy51127312012-09-08 13:08:49 -0400115 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400116 UnMount_Main_Partitions();
Dees_Troy5bf43922012-09-07 16:07:55 -0400117 return true;
118}
119
120int TWPartitionManager::Write_Fstab(void) {
121 FILE *fp;
122 std::vector<TWPartition*>::iterator iter;
123 string Line;
124
125 fp = fopen("/etc/fstab", "w");
126 if (fp == NULL) {
Dees_Troy63c8df72012-09-10 14:02:05 -0400127 LOGI("Can not open /etc/fstab.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400128 return false;
129 }
Dees_Troy63c8df72012-09-10 14:02:05 -0400130 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -0400131 if ((*iter)->Can_Be_Mounted) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400132 Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
Dees_Troy5bf43922012-09-07 16:07:55 -0400133 fputs(Line.c_str(), fp);
Dees_Troy51127312012-09-08 13:08:49 -0400134 // Handle subpartition tracking
135 if ((*iter)->Is_SubPartition) {
136 TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
137 if (ParentPartition)
138 ParentPartition->Has_SubPartition = true;
139 else
140 LOGE("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
141 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400142 }
143 }
144 fclose(fp);
145 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400146}
147
Dees_Troy8170a922012-09-18 15:40:25 -0400148void TWPartitionManager::Output_Partition_Logging(void) {
149 std::vector<TWPartition*>::iterator iter;
150
151 printf("\n\nPartition Logs:\n");
152 for (iter = Partitions.begin(); iter != Partitions.end(); iter++)
153 Output_Partition((*iter));
154}
155
156void TWPartitionManager::Output_Partition(TWPartition* Part) {
157 unsigned long long mb = 1048576;
158
Gary Peck004d48b2012-11-21 16:28:18 -0800159 printf("%s | %s | Size: %iMB", Part->Mount_Point.c_str(), Part->Actual_Block_Device.c_str(), (int)(Part->Size / mb));
Dees_Troy8170a922012-09-18 15:40:25 -0400160 if (Part->Can_Be_Mounted) {
Gary Peck004d48b2012-11-21 16:28:18 -0800161 printf(" Used: %iMB Free: %iMB Backup Size: %iMB", (int)(Part->Used / mb), (int)(Part->Free / mb), (int)(Part->Backup_Size / mb));
Dees_Troy8170a922012-09-18 15:40:25 -0400162 }
Gary Peck004d48b2012-11-21 16:28:18 -0800163 printf("\n Flags: ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500164 if (Part->Can_Be_Mounted)
165 printf("Can_Be_Mounted ");
Gary Peck004d48b2012-11-21 16:28:18 -0800166 if (Part->Can_Be_Wiped)
167 printf("Can_Be_Wiped ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500168 if (Part->Can_Be_Backed_Up)
169 printf("Can_Be_Backed_Up ");
Gary Peck004d48b2012-11-21 16:28:18 -0800170 if (Part->Wipe_During_Factory_Reset)
171 printf("Wipe_During_Factory_Reset ");
172 if (Part->Wipe_Available_in_GUI)
173 printf("Wipe_Available_in_GUI ");
174 if (Part->Is_SubPartition)
175 printf("Is_SubPartition ");
176 if (Part->Has_SubPartition)
177 printf("Has_SubPartition ");
178 if (Part->Removable)
179 printf("Removable ");
180 if (Part->Is_Present)
181 printf("IsPresent ");
182 if (Part->Can_Be_Encrypted)
183 printf("Can_Be_Encrypted ");
184 if (Part->Is_Encrypted)
185 printf("Is_Encrypted ");
186 if (Part->Is_Decrypted)
187 printf("Is_Decrypted ");
188 if (Part->Has_Data_Media)
189 printf("Has_Data_Media ");
190 if (Part->Has_Android_Secure)
191 printf("Has_Android_Secure ");
192 if (Part->Is_Storage)
193 printf("Is_Storage ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500194 if (Part->Is_Settings_Storage)
195 printf("Is_Settings_Storage ");
Dees_Troy68cab492012-12-12 19:29:35 +0000196 if (Part->Ignore_Blkid)
197 printf("Ignore_Blkid ");
Dees_Troy16c2b312013-01-15 16:51:18 +0000198 if (Part->Retain_Layout_Version)
199 printf("Retain_Layout_Version ");
Gary Peck004d48b2012-11-21 16:28:18 -0800200 printf("\n");
201 if (!Part->SubPartition_Of.empty())
202 printf(" SubPartition_Of: %s\n", Part->SubPartition_Of.c_str());
203 if (!Part->Symlink_Path.empty())
204 printf(" Symlink_Path: %s\n", Part->Symlink_Path.c_str());
205 if (!Part->Symlink_Mount_Point.empty())
206 printf(" Symlink_Mount_Point: %s\n", Part->Symlink_Mount_Point.c_str());
207 if (!Part->Primary_Block_Device.empty())
208 printf(" Primary_Block_Device: %s\n", Part->Primary_Block_Device.c_str());
209 if (!Part->Alternate_Block_Device.empty())
210 printf(" Alternate_Block_Device: %s\n", Part->Alternate_Block_Device.c_str());
211 if (!Part->Decrypted_Block_Device.empty())
212 printf(" Decrypted_Block_Device: %s\n", Part->Decrypted_Block_Device.c_str());
213 if (Part->Length != 0)
214 printf(" Length: %i\n", Part->Length);
215 if (!Part->Display_Name.empty())
216 printf(" Display_Name: %s\n", Part->Display_Name.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500217 if (!Part->Storage_Name.empty())
218 printf(" Storage_Name: %s\n", Part->Storage_Name.c_str());
Gary Peck004d48b2012-11-21 16:28:18 -0800219 if (!Part->Backup_Path.empty())
220 printf(" Backup_Path: %s\n", Part->Backup_Path.c_str());
221 if (!Part->Backup_Name.empty())
222 printf(" Backup_Name: %s\n", Part->Backup_Name.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500223 if (!Part->Backup_Display_Name.empty())
224 printf(" Backup_Display_Name: %s\n", Part->Backup_Display_Name.c_str());
Gary Peck004d48b2012-11-21 16:28:18 -0800225 if (!Part->Backup_FileName.empty())
226 printf(" Backup_FileName: %s\n", Part->Backup_FileName.c_str());
227 if (!Part->Storage_Path.empty())
228 printf(" Storage_Path: %s\n", Part->Storage_Path.c_str());
229 if (!Part->Current_File_System.empty())
230 printf(" Current_File_System: %s\n", Part->Current_File_System.c_str());
231 if (!Part->Fstab_File_System.empty())
232 printf(" Fstab_File_System: %s\n", Part->Fstab_File_System.c_str());
233 if (Part->Format_Block_Size != 0)
234 printf(" Format_Block_Size: %i\n", Part->Format_Block_Size);
Dees_Troy094207a2012-09-26 12:00:39 -0400235 if (!Part->MTD_Name.empty())
236 printf(" MTD_Name: %s\n", Part->MTD_Name.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400237 string back_meth = Part->Backup_Method_By_Name();
238 printf(" Backup_Method: %s\n\n", back_meth.c_str());
239}
240
Dees_Troy51a0e822012-09-05 15:24:24 -0400241int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400242 std::vector<TWPartition*>::iterator iter;
243 int ret = false;
244 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400245 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400246
Dees_Troy43d8b002012-09-17 16:00:01 -0400247 if (Local_Path == "/tmp")
248 return true;
249
Dees_Troy5bf43922012-09-07 16:07:55 -0400250 // Iterate through all partitions
251 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400252 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400253 ret = (*iter)->Mount(Display_Error);
254 found = true;
Dees_Troy51127312012-09-08 13:08:49 -0400255 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400256 (*iter)->Mount(Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400257 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400258 }
259 if (found) {
260 return ret;
261 } else if (Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400262 LOGE("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400263 } else {
Dees_Troy51127312012-09-08 13:08:49 -0400264 LOGI("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400265 }
266 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400267}
268
269int TWPartitionManager::Mount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400270 TWPartition* Part = Find_Partition_By_Block(Block);
Dees_Troy5bf43922012-09-07 16:07:55 -0400271
Dees_Troy51127312012-09-08 13:08:49 -0400272 if (Part) {
273 if (Part->Has_SubPartition) {
274 std::vector<TWPartition*>::iterator subpart;
275
276 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
277 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
278 (*subpart)->Mount(Display_Error);
279 }
280 return Part->Mount(Display_Error);
281 } else
282 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400283 }
284 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400285 LOGE("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400286 else
Dees_Troy51127312012-09-08 13:08:49 -0400287 LOGI("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400288 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400289}
290
291int TWPartitionManager::Mount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400292 TWPartition* Part = Find_Partition_By_Name(Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400293
Dees_Troy51127312012-09-08 13:08:49 -0400294 if (Part) {
295 if (Part->Has_SubPartition) {
296 std::vector<TWPartition*>::iterator subpart;
297
298 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
299 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
300 (*subpart)->Mount(Display_Error);
301 }
302 return Part->Mount(Display_Error);
303 } else
304 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400305 }
306 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400307 LOGE("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400308 else
Dees_Troy51127312012-09-08 13:08:49 -0400309 LOGI("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400310 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400311}
312
313int TWPartitionManager::UnMount_By_Path(string Path, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400314 std::vector<TWPartition*>::iterator iter;
315 int ret = false;
316 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400317 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy51127312012-09-08 13:08:49 -0400318
319 // Iterate through all partitions
320 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400321 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400322 ret = (*iter)->UnMount(Display_Error);
323 found = true;
324 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
325 (*iter)->UnMount(Display_Error);
326 }
327 }
328 if (found) {
329 return ret;
330 } else if (Display_Error) {
331 LOGE("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
332 } else {
333 LOGI("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
334 }
335 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400336}
337
338int TWPartitionManager::UnMount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400339 TWPartition* Part = Find_Partition_By_Block(Block);
340
341 if (Part) {
342 if (Part->Has_SubPartition) {
343 std::vector<TWPartition*>::iterator subpart;
344
345 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
346 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
347 (*subpart)->UnMount(Display_Error);
348 }
349 return Part->UnMount(Display_Error);
350 } else
351 return Part->UnMount(Display_Error);
352 }
353 if (Display_Error)
354 LOGE("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
355 else
356 LOGI("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
357 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400358}
359
360int TWPartitionManager::UnMount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400361 TWPartition* Part = Find_Partition_By_Name(Name);
362
363 if (Part) {
364 if (Part->Has_SubPartition) {
365 std::vector<TWPartition*>::iterator subpart;
366
367 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
368 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
369 (*subpart)->UnMount(Display_Error);
370 }
371 return Part->UnMount(Display_Error);
372 } else
373 return Part->UnMount(Display_Error);
374 }
375 if (Display_Error)
376 LOGE("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
377 else
378 LOGI("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
379 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400380}
381
382int TWPartitionManager::Is_Mounted_By_Path(string Path) {
Dees_Troy51127312012-09-08 13:08:49 -0400383 TWPartition* Part = Find_Partition_By_Path(Path);
384
385 if (Part)
386 return Part->Is_Mounted();
387 else
388 LOGI("Is_Mounted: Unable to find partition for path '%s'\n", Path.c_str());
389 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400390}
391
392int TWPartitionManager::Is_Mounted_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400393 TWPartition* Part = Find_Partition_By_Block(Block);
394
395 if (Part)
396 return Part->Is_Mounted();
397 else
398 LOGI("Is_Mounted: Unable to find partition for block '%s'\n", Block.c_str());
399 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400400}
401
402int TWPartitionManager::Is_Mounted_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400403 TWPartition* Part = Find_Partition_By_Name(Name);
404
405 if (Part)
406 return Part->Is_Mounted();
407 else
408 LOGI("Is_Mounted: Unable to find partition for name '%s'\n", Name.c_str());
409 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400410}
411
Dees_Troy5bf43922012-09-07 16:07:55 -0400412int TWPartitionManager::Mount_Current_Storage(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400413 string current_storage_path = DataManager::GetCurrentStoragePath();
414
415 if (Mount_By_Path(current_storage_path, Display_Error)) {
416 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
417 if (FreeStorage)
418 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
419 return true;
420 }
421 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400422}
423
Dees_Troy5bf43922012-09-07 16:07:55 -0400424int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) {
425 return Mount_By_Path(DataManager::GetSettingsStoragePath(), Display_Error);
426}
427
428TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) {
429 std::vector<TWPartition*>::iterator iter;
Dees_Troy38bd7602012-09-14 13:33:53 -0400430 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400431
432 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400433 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path))
Dees_Troy5bf43922012-09-07 16:07:55 -0400434 return (*iter);
435 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400436 return NULL;
437}
438
Dees_Troy5bf43922012-09-07 16:07:55 -0400439TWPartition* TWPartitionManager::Find_Partition_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400440 std::vector<TWPartition*>::iterator iter;
441
442 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400443 if ((*iter)->Primary_Block_Device == Block || (*iter)->Alternate_Block_Device == Block || ((*iter)->Is_Decrypted && (*iter)->Decrypted_Block_Device == Block))
Dees_Troy51127312012-09-08 13:08:49 -0400444 return (*iter);
445 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400446 return NULL;
Dees_Troy5bf43922012-09-07 16:07:55 -0400447}
448
449TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400450 std::vector<TWPartition*>::iterator iter;
451
452 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
453 if ((*iter)->Display_Name == Name)
454 return (*iter);
455 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400456 return NULL;
457}
Dees_Troy51a0e822012-09-05 15:24:24 -0400458
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400459int TWPartitionManager::Check_Backup_Name(bool Display_Error) {
460 // Check the backup name to ensure that it is the correct size and contains only valid characters
461 // and that a backup with that name doesn't already exist
462 char backup_name[MAX_BACKUP_NAME_LEN];
463 char backup_loc[255], tw_image_dir[255];
464 int copy_size;
465 int index, cur_char;
466 string Backup_Name, Backup_Loc;
467
468 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
469 copy_size = Backup_Name.size();
470 // Check size
471 if (copy_size > MAX_BACKUP_NAME_LEN) {
472 if (Display_Error)
473 LOGE("Backup name is too long.\n");
474 return -2;
475 }
476
477 // Check each character
478 strncpy(backup_name, Backup_Name.c_str(), copy_size);
Dees_Troya13d74f2013-03-24 08:54:55 -0500479 if (copy_size == 1 && strncmp(backup_name, "0", 1) == 0)
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400480 return 0; // A "0" (zero) means to use the current timestamp for the backup name
481 for (index=0; index<copy_size; index++) {
482 cur_char = (int)backup_name[index];
483 if (cur_char == 32 || (cur_char >= 48 && cur_char <= 57) || (cur_char >= 65 && cur_char <= 91) || cur_char == 93 || cur_char == 95 || (cur_char >= 97 && cur_char <= 123) || cur_char == 125 || cur_char == 45 || cur_char == 46) {
484 // These are valid characters
485 // Numbers
486 // Upper case letters
487 // Lower case letters
488 // Space
489 // and -_.{}[]
490 } else {
491 if (Display_Error)
492 LOGE("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
493 return -3;
494 }
495 }
496
497 // Check to make sure that a backup with this name doesn't already exist
498 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Loc);
499 strcpy(backup_loc, Backup_Loc.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500500 sprintf(tw_image_dir,"%s/%s", backup_loc, Backup_Name.c_str());
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400501 if (TWFunc::Path_Exists(tw_image_dir)) {
502 if (Display_Error)
503 LOGE("A backup with this name already exists.\n");
504 return -4;
505 }
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400506 // No problems found, return 0
507 return 0;
508}
509
Dees_Troy43d8b002012-09-17 16:00:01 -0400510bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename)
511{
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500512 string command;
Dees_Troy43d8b002012-09-17 16:00:01 -0400513 string Full_File = Backup_Folder + Backup_Filename;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500514 string result;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500515 twrpDigest md5sum;
Dees_Troy43d8b002012-09-17 16:00:01 -0400516
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500517 if (!generate_md5)
Dees_Troy43d8b002012-09-17 16:00:01 -0400518 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -0400519
Dees_Troyb46a6842012-09-25 11:06:46 -0400520 TWFunc::GUI_Operation_Text(TW_GENERATE_MD5_TEXT, "Generating MD5");
Dees_Troyc51f1f92012-09-20 15:32:13 -0400521 ui_print(" * Generating md5...\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400522
523 if (TWFunc::Path_Exists(Full_File)) {
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500524 md5sum.setfn(Backup_Folder + Backup_Filename);
525 if (md5sum.computeMD5() == 0)
526 if (md5sum.write_md5digest() == 0)
527 ui_print(" * MD5 Created.\n");
528 else
529 return -1;
530 else
Dees_Troyc5865ab2012-09-24 15:08:04 -0400531 ui_print(" * MD5 Error!\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400532 } else {
533 char filename[512];
534 int index = 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500535 string strfn;
Dees_Troy43d8b002012-09-17 16:00:01 -0400536 sprintf(filename, "%s%03i", Full_File.c_str(), index);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500537 strfn = filename;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400538 while (TWFunc::Path_Exists(filename) == true) {
bigbiff bigbiff65a4c732013-03-15 15:17:50 -0400539 md5sum.setfn(filename);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500540 if (md5sum.computeMD5() == 0) {
541 if (md5sum.write_md5digest() != 0)
542 {
543 ui_print(" * MD5 Error.\n");
544 return false;
545 }
546 }
547 else {
548 return -1;
Dees_Troy43d8b002012-09-17 16:00:01 -0400549 }
550 index++;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400551 sprintf(filename, "%s%03i", Full_File.c_str(), index);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500552 strfn = filename;
Dees_Troy43d8b002012-09-17 16:00:01 -0400553 }
554 if (index == 0) {
555 LOGE("Backup file: '%s' not found!\n", filename);
556 return false;
557 }
Dees_Troyc5865ab2012-09-24 15:08:04 -0400558 ui_print(" * MD5 Created.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400559 }
560 return true;
561}
562
Dees_Troy093b7642012-09-21 15:59:38 -0400563bool TWPartitionManager::Backup_Partition(TWPartition* Part, string Backup_Folder, bool generate_md5, unsigned long long* img_bytes_remaining, unsigned long long* file_bytes_remaining, unsigned long *img_time, unsigned long *file_time, unsigned long long *img_bytes, unsigned long long *file_bytes) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400564 time_t start, stop;
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500565 int img_bps;
566 unsigned long long file_bps;
Dees_Troy093b7642012-09-21 15:59:38 -0400567 unsigned long total_time, remain_time, section_time;
568 int use_compression, backup_time;
569 float pos;
Dees_Troy43d8b002012-09-17 16:00:01 -0400570
571 if (Part == NULL)
572 return true;
573
Dees_Troy093b7642012-09-21 15:59:38 -0400574 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
575
576 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
577 if (use_compression)
578 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
579 else
580 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
581
582 // We know the speed for both, how far into the whole backup are we, based on time
583 total_time = (*img_bytes / (unsigned long)img_bps) + (*file_bytes / (unsigned long)file_bps);
584 remain_time = (*img_bytes_remaining / (unsigned long)img_bps) + (*file_bytes_remaining / (unsigned long)file_bps);
585
586 pos = (total_time - remain_time) / (float) total_time;
587 ui->SetProgress(pos);
588
589 LOGI("Estimated Total time: %lu Estimated remaining time: %lu\n", total_time, remain_time);
590
591 // And get the time
592 if (Part->Backup_Method == 1)
593 section_time = Part->Backup_Size / file_bps;
594 else
595 section_time = Part->Backup_Size / img_bps;
596
597 // Set the position
598 pos = section_time / (float) total_time;
599 ui->ShowProgress(pos, section_time);
600
Dees_Troy43d8b002012-09-17 16:00:01 -0400601 time(&start);
602
603 if (Part->Backup(Backup_Folder)) {
Dees_Troy8170a922012-09-18 15:40:25 -0400604 if (Part->Has_SubPartition) {
605 std::vector<TWPartition*>::iterator subpart;
606
607 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500608 if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
Dees_Troy8170a922012-09-18 15:40:25 -0400609 if (!(*subpart)->Backup(Backup_Folder))
610 return false;
611 if (!Make_MD5(generate_md5, Backup_Folder, (*subpart)->Backup_FileName))
612 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400613 if (Part->Backup_Method == 1) {
614 *file_bytes_remaining -= (*subpart)->Backup_Size;
615 } else {
616 *img_bytes_remaining -= (*subpart)->Backup_Size;
617 }
Dees_Troy8170a922012-09-18 15:40:25 -0400618 }
619 }
620 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400621 time(&stop);
Dees_Troy093b7642012-09-21 15:59:38 -0400622 backup_time = (int) difftime(stop, start);
623 LOGI("Partition Backup time: %d\n", backup_time);
Dees_Troy43d8b002012-09-17 16:00:01 -0400624 if (Part->Backup_Method == 1) {
625 *file_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400626 *file_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400627 } else {
628 *img_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400629 *img_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400630 }
631 return Make_MD5(generate_md5, Backup_Folder, Part->Backup_FileName);
632 } else {
633 return false;
634 }
635}
636
637int TWPartitionManager::Run_Backup(void) {
638 int check, do_md5, partition_count = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500639 string Backup_Folder, Backup_Name, Full_Backup_Path, Backup_List, backup_path;
Dees_Troy8170a922012-09-18 15:40:25 -0400640 unsigned long long total_bytes = 0, file_bytes = 0, img_bytes = 0, free_space = 0, img_bytes_remaining, file_bytes_remaining, subpart_size;
Dees_Troy43d8b002012-09-17 16:00:01 -0400641 unsigned long img_time = 0, file_time = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500642 TWPartition* backup_part = NULL;
Dees_Troy43d8b002012-09-17 16:00:01 -0400643 TWPartition* storage = NULL;
Dees_Troy8170a922012-09-18 15:40:25 -0400644 std::vector<TWPartition*>::iterator subpart;
Dees_Troy43d8b002012-09-17 16:00:01 -0400645 struct tm *t;
646 time_t start, stop, seconds, total_start, total_stop;
Dees_Troya13d74f2013-03-24 08:54:55 -0500647 size_t start_pos = 0, end_pos = 0;
Dees_Troy43d8b002012-09-17 16:00:01 -0400648 seconds = time(0);
649 t = localtime(&seconds);
650
651 time(&total_start);
652
653 Update_System_Details();
654
655 if (!Mount_Current_Storage(true))
656 return false;
657
658 DataManager::GetValue(TW_SKIP_MD5_GENERATE_VAR, do_md5);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400659 if (do_md5 == 0)
Dees_Troy43d8b002012-09-17 16:00:01 -0400660 do_md5 = true;
Dees_Troyc5865ab2012-09-24 15:08:04 -0400661 else
662 do_md5 = false;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400663
Dees_Troy43d8b002012-09-17 16:00:01 -0400664 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Folder);
665 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400666 if (Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name.empty()) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400667 char timestamp[255];
668 sprintf(timestamp,"%04d-%02d-%02d--%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
669 Backup_Name = timestamp;
670 }
671 LOGI("Backup Name is: '%s'\n", Backup_Name.c_str());
672 Full_Backup_Path = Backup_Folder + "/" + Backup_Name + "/";
673 LOGI("Full_Backup_Path is: '%s'\n", Full_Backup_Path.c_str());
674
Dees_Troy43d8b002012-09-17 16:00:01 -0400675 LOGI("Calculating backup details...\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500676 DataManager::GetValue("tw_backup_list", Backup_List);
677 if (!Backup_List.empty()) {
678 end_pos = Backup_List.find(";", start_pos);
679 while (end_pos != string::npos && start_pos < Backup_List.size()) {
680 backup_path = Backup_List.substr(start_pos, end_pos - start_pos);
681 backup_part = Find_Partition_By_Path(backup_path);
682 if (backup_part != NULL) {
683 partition_count++;
684 if (backup_part->Backup_Method == 1)
685 file_bytes += backup_part->Backup_Size;
686 else
687 img_bytes += backup_part->Backup_Size;
688 if (backup_part->Has_SubPartition) {
689 std::vector<TWPartition*>::iterator subpart;
690
691 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
692 if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == backup_part->Mount_Point) {
693 partition_count++;
694 if ((*subpart)->Backup_Method == 1)
695 file_bytes += (*subpart)->Backup_Size;
696 else
697 img_bytes += (*subpart)->Backup_Size;
698 }
699 }
Dees_Troy8170a922012-09-18 15:40:25 -0400700 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500701 } else {
702 LOGE("Unable to locate '%s' partition for backup calculations.\n", backup_path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400703 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500704 start_pos = end_pos + 1;
705 end_pos = Backup_List.find(";", start_pos);
Dees_Troy43d8b002012-09-17 16:00:01 -0400706 }
707 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400708
709 if (partition_count == 0) {
710 ui_print("No partitions selected for backup.\n");
711 return false;
712 }
713 total_bytes = file_bytes + img_bytes;
714 ui_print(" * Total number of partitions to back up: %d\n", partition_count);
715 ui_print(" * Total size of all data: %lluMB\n", total_bytes / 1024 / 1024);
716 storage = Find_Partition_By_Path(DataManager::GetCurrentStoragePath());
717 if (storage != NULL) {
718 free_space = storage->Free;
719 ui_print(" * Available space: %lluMB\n", free_space / 1024 / 1024);
720 } else {
721 LOGE("Unable to locate storage device.\n");
722 return false;
723 }
Dees_Troyd4b22b02013-01-18 17:17:58 +0000724 if (free_space - (32 * 1024 * 1024) < total_bytes) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400725 // We require an extra 32MB just in case
726 LOGE("Not enough free space on storage.\n");
727 return false;
728 }
729 img_bytes_remaining = img_bytes;
730 file_bytes_remaining = file_bytes;
731
Dees_Troyd4b22b02013-01-18 17:17:58 +0000732 ui_print("\n[BACKUP STARTED]\n");
733 ui_print(" * Backup Folder: %s\n", Full_Backup_Path.c_str());
734 if (!TWFunc::Recursive_Mkdir(Full_Backup_Path)) {
735 LOGE("Failed to make backup folder.\n");
736 return false;
737 }
738
Dees_Troy093b7642012-09-21 15:59:38 -0400739 ui->SetProgress(0.0);
740
Dees_Troya13d74f2013-03-24 08:54:55 -0500741 start_pos = 0;
742 end_pos = Backup_List.find(";", start_pos);
743 while (end_pos != string::npos && start_pos < Backup_List.size()) {
744 backup_path = Backup_List.substr(start_pos, end_pos - start_pos);
745 backup_part = Find_Partition_By_Path(backup_path);
746 if (backup_part != NULL) {
747 if (!Backup_Partition(backup_part, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
748 return false;
749 } else {
750 LOGE("Unable to locate '%s' partition for backup process.\n", backup_path.c_str());
751 }
752 start_pos = end_pos + 1;
753 end_pos = Backup_List.find(";", start_pos);
754 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400755
756 // Average BPS
757 if (img_time == 0)
758 img_time = 1;
759 if (file_time == 0)
760 file_time = 1;
Dees_Troy093b7642012-09-21 15:59:38 -0400761 int img_bps = (int)img_bytes / (int)img_time;
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500762 unsigned long long file_bps = file_bytes / (int)file_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400763
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500764 ui_print("Average backup rate for file systems: %llu MB/sec\n", (file_bps / (1024 * 1024)));
Dees_Troy43d8b002012-09-17 16:00:01 -0400765 ui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));
766
767 time(&total_stop);
768 int total_time = (int) difftime(total_stop, total_start);
769 unsigned long long actual_backup_size = TWFunc::Get_Folder_Size(Full_Backup_Path, true);
770 actual_backup_size /= (1024LLU * 1024LLU);
771
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500772 int prev_img_bps, use_compression;
773 unsigned long long prev_file_bps;
Dees_Troy093b7642012-09-21 15:59:38 -0400774 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, prev_img_bps);
775 img_bps += (prev_img_bps * 4);
776 img_bps /= 5;
777
778 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
779 if (use_compression)
780 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, prev_file_bps);
781 else
782 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, prev_file_bps);
783 file_bps += (prev_file_bps * 4);
784 file_bps /= 5;
785
786 DataManager::SetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
787 if (use_compression)
788 DataManager::SetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
789 else
790 DataManager::SetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
791
Dees_Troy43d8b002012-09-17 16:00:01 -0400792 ui_print("[%llu MB TOTAL BACKED UP]\n", actual_backup_size);
793 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400794 UnMount_Main_Partitions();
Dees_Troy43d8b002012-09-17 16:00:01 -0400795 ui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000796 string backup_log = Full_Backup_Path + "recovery.log";
797 TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644);
798 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400799}
800
Dees_Troy093b7642012-09-21 15:59:38 -0400801bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Name, int partition_count) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400802 time_t Start, Stop;
803 time(&Start);
Dees_Troy093b7642012-09-21 15:59:38 -0400804 ui->ShowProgress(1.0 / (float)partition_count, 150);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400805 if (!Part->Restore(Restore_Name))
806 return false;
Dees_Troy8170a922012-09-18 15:40:25 -0400807 if (Part->Has_SubPartition) {
808 std::vector<TWPartition*>::iterator subpart;
809
810 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
811 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
812 if (!(*subpart)->Restore(Restore_Name))
813 return false;
814 }
815 }
816 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400817 time(&Stop);
Dees_Troya13d74f2013-03-24 08:54:55 -0500818 ui_print("[%s done (%d seconds)]\n\n", Part->Backup_Display_Name.c_str(), (int)difftime(Stop, Start));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400819 return true;
820}
821
Dees_Troy51a0e822012-09-05 15:24:24 -0400822int TWPartitionManager::Run_Restore(string Restore_Name) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400823 int check_md5, check, partition_count = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500824 TWPartition* restore_part = NULL;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400825 time_t rStart, rStop;
826 time(&rStart);
Dees_Troya13d74f2013-03-24 08:54:55 -0500827 string Restore_List, restore_path;
828 size_t start_pos = 0, end_pos;
Dees_Troy43d8b002012-09-17 16:00:01 -0400829
Dees_Troy4a2a1262012-09-18 09:33:47 -0400830 ui_print("\n[RESTORE STARTED]\n\n");
831 ui_print("Restore folder: '%s'\n", Restore_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400832
Dees_Troy4a2a1262012-09-18 09:33:47 -0400833 if (!Mount_Current_Storage(true))
834 return false;
835
836 DataManager::GetValue(TW_SKIP_MD5_CHECK_VAR, check_md5);
Dees_Troya13d74f2013-03-24 08:54:55 -0500837 if (check_md5 > 0) {
838 // Check MD5 files first before restoring to ensure that all of them match before starting a restore
839 TWFunc::GUI_Operation_Text(TW_VERIFY_MD5_TEXT, "Verifying MD5");
840 ui_print("Verifying MD5...\n");
841 } else {
842 ui_print("Skipping MD5 check based on user setting.\n");
843 }
844 DataManager::GetValue("tw_restore_selected", Restore_List);
845 if (!Restore_List.empty()) {
846 end_pos = Restore_List.find(";", start_pos);
847 while (end_pos != string::npos && start_pos < Restore_List.size()) {
848 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
849 restore_part = Find_Partition_By_Path(restore_path);
850 if (restore_part != NULL) {
851 partition_count++;
852 if (check_md5 > 0 && !restore_part->Check_MD5(Restore_Name))
853 return false;
854 if (restore_part->Has_SubPartition) {
855 std::vector<TWPartition*>::iterator subpart;
856
857 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
858 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == restore_part->Mount_Point) {
859 if (!(*subpart)->Check_MD5(Restore_Name))
860 return false;
861 }
862 }
863 }
864 } else {
865 LOGE("Unable to locate '%s' partition for restoring.\n", restore_path.c_str());
866 }
867 start_pos = end_pos + 1;
868 end_pos = Restore_List.find(";", start_pos);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400869 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400870 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400871
872 if (partition_count == 0) {
873 LOGE("No partitions selected for restore.\n");
874 return false;
875 }
876
Dees_Troy4a2a1262012-09-18 09:33:47 -0400877 ui_print("Restoring %i partitions...\n", partition_count);
Dees_Troy093b7642012-09-21 15:59:38 -0400878 ui->SetProgress(0.0);
Dees_Troya13d74f2013-03-24 08:54:55 -0500879 start_pos = 0;
880 if (!Restore_List.empty()) {
881 end_pos = Restore_List.find(";", start_pos);
882 while (end_pos != string::npos && start_pos < Restore_List.size()) {
883 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
884 restore_part = Find_Partition_By_Path(restore_path);
885 if (restore_part != NULL) {
886 partition_count++;
887 if (!Restore_Partition(restore_part, Restore_Name, partition_count))
888 return false;
889 } else {
890 LOGE("Unable to locate '%s' partition for restoring.\n", restore_path.c_str());
891 }
892 start_pos = end_pos + 1;
893 end_pos = Restore_List.find(";", start_pos);
894 }
895 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400896
Dees_Troyb46a6842012-09-25 11:06:46 -0400897 TWFunc::GUI_Operation_Text(TW_UPDATE_SYSTEM_DETAILS_TEXT, "Updating System Details");
Dees_Troy43d8b002012-09-17 16:00:01 -0400898 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400899 UnMount_Main_Partitions();
Dees_Troy4a2a1262012-09-18 09:33:47 -0400900 time(&rStop);
901 ui_print("[RESTORE COMPLETED IN %d SECONDS]\n\n",(int)difftime(rStop,rStart));
Dees_Troy63c8df72012-09-10 14:02:05 -0400902 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400903}
904
905void TWPartitionManager::Set_Restore_Files(string Restore_Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -0400906 // Start with the default values
Dees_Troya13d74f2013-03-24 08:54:55 -0500907 string Restore_List;
Dees_Troy63c8df72012-09-10 14:02:05 -0400908 bool get_date = true;
909
910 DIR* d;
911 d = opendir(Restore_Name.c_str());
912 if (d == NULL)
913 {
914 LOGE("Error opening %s\n", Restore_Name.c_str());
915 return;
916 }
917
918 struct dirent* de;
919 while ((de = readdir(d)) != NULL)
920 {
921 // Strip off three components
922 char str[256];
923 char* label;
924 char* fstype = NULL;
925 char* extn = NULL;
926 char* ptr;
927
928 strcpy(str, de->d_name);
929 if (strlen(str) <= 2)
930 continue;
931
932 if (get_date) {
933 char file_path[255];
934 struct stat st;
935
936 strcpy(file_path, Restore_Name.c_str());
937 strcat(file_path, "/");
938 strcat(file_path, str);
939 stat(file_path, &st);
940 string backup_date = ctime((const time_t*)(&st.st_mtime));
941 DataManager::SetValue(TW_RESTORE_FILE_DATE, backup_date);
942 get_date = false;
943 }
944
945 label = str;
946 ptr = label;
947 while (*ptr && *ptr != '.') ptr++;
948 if (*ptr == '.')
949 {
950 *ptr = 0x00;
951 ptr++;
952 fstype = ptr;
953 }
954 while (*ptr && *ptr != '.') ptr++;
955 if (*ptr == '.')
956 {
957 *ptr = 0x00;
958 ptr++;
959 extn = ptr;
960 }
961
Dees_Troya13d74f2013-03-24 08:54:55 -0500962 if (strcmp(fstype, "log") == 0) continue;
963 int extnlength = strlen(extn);
964 if (extn == NULL || (extnlength != 3 && extnlength != 6)) continue;
965 if (extnlength == 3 && strncmp(extn, "win", 3) != 0) continue;
966 if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
Dees_Troy63c8df72012-09-10 14:02:05 -0400967
968 TWPartition* Part = Find_Partition_By_Path(label);
969 if (Part == NULL)
970 {
971 LOGE(" Unable to locate partition by backup name: '%s'\n", label);
972 continue;
973 }
974
975 Part->Backup_FileName = de->d_name;
976 if (strlen(extn) > 3) {
977 Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3);
978 }
979
Dees_Troya13d74f2013-03-24 08:54:55 -0500980 Restore_List += Part->Backup_Path + ";";
Dees_Troy63c8df72012-09-10 14:02:05 -0400981 }
982 closedir(d);
983
Dees_Troya13d74f2013-03-24 08:54:55 -0500984 // Set the final value
985 DataManager::SetValue("tw_restore_list", Restore_List);
986 DataManager::SetValue("tw_restore_selected", Restore_List);
Dees_Troy51a0e822012-09-05 15:24:24 -0400987 return;
988}
989
990int TWPartitionManager::Wipe_By_Path(string Path) {
Dees_Troy63c8df72012-09-10 14:02:05 -0400991 std::vector<TWPartition*>::iterator iter;
992 int ret = false;
993 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400994 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy63c8df72012-09-10 14:02:05 -0400995
996 // Iterate through all partitions
997 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400998 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troye58d5262012-09-21 12:27:57 -0400999 if (Path == "/and-sec")
1000 ret = (*iter)->Wipe_AndSec();
1001 else
1002 ret = (*iter)->Wipe();
Dees_Troy63c8df72012-09-10 14:02:05 -04001003 found = true;
1004 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
1005 (*iter)->Wipe();
1006 }
1007 }
1008 if (found) {
1009 return ret;
1010 } else
1011 LOGE("Wipe: Unable to find partition for path '%s'\n", Local_Path.c_str());
1012 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001013}
1014
1015int TWPartitionManager::Wipe_By_Block(string Block) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001016 TWPartition* Part = Find_Partition_By_Block(Block);
1017
1018 if (Part) {
1019 if (Part->Has_SubPartition) {
1020 std::vector<TWPartition*>::iterator subpart;
1021
1022 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1023 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1024 (*subpart)->Wipe();
1025 }
1026 return Part->Wipe();
1027 } else
1028 return Part->Wipe();
1029 }
1030 LOGE("Wipe: Unable to find partition for block '%s'\n", Block.c_str());
1031 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001032}
1033
1034int TWPartitionManager::Wipe_By_Name(string Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001035 TWPartition* Part = Find_Partition_By_Name(Name);
1036
1037 if (Part) {
1038 if (Part->Has_SubPartition) {
1039 std::vector<TWPartition*>::iterator subpart;
1040
1041 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1042 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1043 (*subpart)->Wipe();
1044 }
1045 return Part->Wipe();
1046 } else
1047 return Part->Wipe();
1048 }
1049 LOGE("Wipe: Unable to find partition for name '%s'\n", Name.c_str());
1050 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001051}
1052
1053int TWPartitionManager::Factory_Reset(void) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001054 std::vector<TWPartition*>::iterator iter;
1055 int ret = true;
1056
1057 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001058 if ((*iter)->Wipe_During_Factory_Reset && (*iter)->Is_Present) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001059 if (!(*iter)->Wipe())
1060 ret = false;
Dees_Troy094207a2012-09-26 12:00:39 -04001061 } else if ((*iter)->Has_Android_Secure) {
1062 if (!(*iter)->Wipe_AndSec())
1063 ret = false;
Dees_Troy63c8df72012-09-10 14:02:05 -04001064 }
1065 }
1066 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001067}
1068
Dees_Troy38bd7602012-09-14 13:33:53 -04001069int TWPartitionManager::Wipe_Dalvik_Cache(void) {
1070 struct stat st;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001071 vector <string> dir;
Dees_Troy38bd7602012-09-14 13:33:53 -04001072
1073 if (!Mount_By_Path("/data", true))
1074 return false;
1075
1076 if (!Mount_By_Path("/cache", true))
1077 return false;
1078
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001079 dir.push_back("/data/dalvik-cache");
1080 dir.push_back("/cache/dalvik-cache");
1081 dir.push_back("/cache/dc");
Dees_Troy38bd7602012-09-14 13:33:53 -04001082 ui_print("\nWiping Dalvik Cache Directories...\n");
Dees_Troya13d74f2013-03-24 08:54:55 -05001083 for (unsigned i = 0; i < dir.size(); ++i) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001084 if (stat(dir.at(i).c_str(), &st) == 0) {
1085 TWFunc::removeDir(dir.at(i), false);
1086 ui_print("Cleaned: %s...\n", dir.at(i).c_str());
1087 }
1088 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001089 TWPartition* sdext = Find_Partition_By_Path("/sd-ext");
1090 if (sdext != NULL) {
1091 if (sdext->Is_Present && sdext->Mount(false)) {
1092 if (stat("/sd-ext/dalvik-cache", &st) == 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001093 TWFunc::removeDir("/sd-ext/dalvik-cache", false);
1094 ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
1095 }
1096 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001097 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001098 ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
1099 return true;
1100}
1101
1102int TWPartitionManager::Wipe_Rotate_Data(void) {
1103 if (!Mount_By_Path("/data", true))
1104 return false;
1105
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001106 unlink("/data/misc/akmd*");
1107 unlink("/data/misc/rild*");
Dees_Troy38bd7602012-09-14 13:33:53 -04001108 ui_print("Rotation data wiped.\n");
1109 return true;
1110}
1111
1112int TWPartitionManager::Wipe_Battery_Stats(void) {
1113 struct stat st;
1114
1115 if (!Mount_By_Path("/data", true))
1116 return false;
1117
1118 if (0 != stat("/data/system/batterystats.bin", &st)) {
1119 ui_print("No Battery Stats Found. No Need To Wipe.\n");
1120 } else {
1121 remove("/data/system/batterystats.bin");
1122 ui_print("Cleared battery stats.\n");
1123 }
1124 return true;
1125}
1126
Dees_Troy2ff5a8d2012-09-26 14:53:02 -04001127int TWPartitionManager::Wipe_Android_Secure(void) {
1128 std::vector<TWPartition*>::iterator iter;
1129 int ret = false;
1130 bool found = false;
1131
1132 // Iterate through all partitions
1133 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1134 if ((*iter)->Has_Android_Secure) {
1135 ret = (*iter)->Wipe_AndSec();
1136 found = true;
1137 }
1138 }
1139 if (found) {
1140 return ret;
1141 } else {
1142 LOGE("No android secure partitions found.\n");
1143 }
1144 return false;
1145}
1146
Dees_Troy38bd7602012-09-14 13:33:53 -04001147int TWPartitionManager::Format_Data(void) {
1148 TWPartition* dat = Find_Partition_By_Path("/data");
1149
1150 if (dat != NULL) {
1151 if (!dat->UnMount(true))
1152 return false;
1153
1154 return dat->Wipe_Encryption();
1155 } else {
1156 LOGE("Unable to locate /data.\n");
1157 return false;
1158 }
1159 return false;
1160}
1161
1162int TWPartitionManager::Wipe_Media_From_Data(void) {
1163 TWPartition* dat = Find_Partition_By_Path("/data");
1164
1165 if (dat != NULL) {
1166 if (!dat->Has_Data_Media) {
1167 LOGE("This device does not have /data/media\n");
1168 return false;
1169 }
1170 if (!dat->Mount(true))
1171 return false;
1172
1173 ui_print("Wiping internal storage -- /data/media...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001174 TWFunc::removeDir("/data/media", false);
1175 if (mkdir("/data/media", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
1176 return -1;
Dees_Troy38bd7602012-09-14 13:33:53 -04001177 if (dat->Has_Data_Media) {
1178 dat->Recreate_Media_Folder();
1179 }
1180 return true;
1181 } else {
1182 LOGE("Unable to locate /data.\n");
1183 return false;
1184 }
1185 return false;
1186}
1187
Dees_Troy51a0e822012-09-05 15:24:24 -04001188void TWPartitionManager::Refresh_Sizes(void) {
Dees_Troy51127312012-09-08 13:08:49 -04001189 Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -04001190 return;
1191}
1192
1193void TWPartitionManager::Update_System_Details(void) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001194 std::vector<TWPartition*>::iterator iter;
Dees_Troy51127312012-09-08 13:08:49 -04001195 int data_size = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -04001196
Dees_Troy32c8eb82012-09-11 15:28:06 -04001197 ui_print("Updating partition details...\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001198 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -04001199 if ((*iter)->Can_Be_Mounted) {
1200 (*iter)->Update_Size(true);
1201 if ((*iter)->Mount_Point == "/system") {
1202 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1203 DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size);
1204 } else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") {
1205 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
1206 } else if ((*iter)->Mount_Point == "/cache") {
1207 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1208 DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size);
1209 } else if ((*iter)->Mount_Point == "/sd-ext") {
1210 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1211 DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size);
1212 if ((*iter)->Backup_Size == 0) {
1213 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0);
1214 DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0);
1215 } else
1216 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1);
Dees_Troye58d5262012-09-21 12:27:57 -04001217 } else if ((*iter)->Has_Android_Secure) {
Dees_Troy8170a922012-09-18 15:40:25 -04001218 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
Dees_Troye58d5262012-09-21 12:27:57 -04001219 DataManager::SetValue(TW_BACKUP_ANDSEC_SIZE, backup_display_size);
Dees_Troy8170a922012-09-18 15:40:25 -04001220 if ((*iter)->Backup_Size == 0) {
1221 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 0);
1222 DataManager::SetValue(TW_BACKUP_ANDSEC_VAR, 0);
1223 } else
1224 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 1);
Dees_Troy2c50e182012-09-26 20:05:28 -04001225 } else if ((*iter)->Mount_Point == "/boot") {
1226 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1227 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
1228 if ((*iter)->Backup_Size == 0) {
1229 DataManager::SetValue("tw_has_boot_partition", 0);
1230 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
1231 } else
1232 DataManager::SetValue("tw_has_boot_partition", 1);
Dees_Troy51127312012-09-08 13:08:49 -04001233 }
Dees_Troyab10ee22012-09-21 14:27:30 -04001234#ifdef SP1_NAME
1235 if ((*iter)->Backup_Name == EXPAND(SP1_NAME)) {
1236 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1237 DataManager::SetValue(TW_BACKUP_SP1_SIZE, backup_display_size);
1238 }
1239#endif
1240#ifdef SP2_NAME
1241 if ((*iter)->Backup_Name == EXPAND(SP2_NAME)) {
1242 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1243 DataManager::SetValue(TW_BACKUP_SP2_SIZE, backup_display_size);
1244 }
1245#endif
1246#ifdef SP3_NAME
1247 if ((*iter)->Backup_Name == EXPAND(SP3_NAME)) {
1248 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1249 DataManager::SetValue(TW_BACKUP_SP3_SIZE, backup_display_size);
1250 }
1251#endif
Dees_Troyaa9cc402012-10-13 12:14:05 -04001252 } else {
1253 // Handle unmountable partitions in case we reset defaults
1254 if ((*iter)->Mount_Point == "/boot") {
1255 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1256 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
1257 if ((*iter)->Backup_Size == 0) {
1258 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 0);
1259 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
1260 } else
1261 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 1);
1262 } else if ((*iter)->Mount_Point == "/recovery") {
1263 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1264 DataManager::SetValue(TW_BACKUP_RECOVERY_SIZE, backup_display_size);
1265 if ((*iter)->Backup_Size == 0) {
1266 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 0);
1267 DataManager::SetValue(TW_BACKUP_RECOVERY_VAR, 0);
1268 } else
1269 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 1);
Gary Peck82599a82012-11-21 16:23:12 -08001270 } else if ((*iter)->Mount_Point == "/data") {
1271 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
Dees_Troyaa9cc402012-10-13 12:14:05 -04001272 }
1273#ifdef SP1_NAME
1274 if ((*iter)->Backup_Name == EXPAND(SP1_NAME)) {
1275 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1276 DataManager::SetValue(TW_BACKUP_SP1_SIZE, backup_display_size);
1277 }
1278#endif
1279#ifdef SP2_NAME
1280 if ((*iter)->Backup_Name == EXPAND(SP2_NAME)) {
1281 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1282 DataManager::SetValue(TW_BACKUP_SP2_SIZE, backup_display_size);
1283 }
1284#endif
1285#ifdef SP3_NAME
1286 if ((*iter)->Backup_Name == EXPAND(SP3_NAME)) {
1287 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1288 DataManager::SetValue(TW_BACKUP_SP3_SIZE, backup_display_size);
1289 }
1290#endif
Dees_Troy51127312012-09-08 13:08:49 -04001291 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001292 }
Dees_Troy51127312012-09-08 13:08:49 -04001293 DataManager::SetValue(TW_BACKUP_DATA_SIZE, data_size);
1294 string current_storage_path = DataManager::GetCurrentStoragePath();
1295 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
Dees_Troy8170a922012-09-18 15:40:25 -04001296 if (FreeStorage != NULL) {
1297 // Attempt to mount storage
1298 if (!FreeStorage->Mount(false)) {
1299 // We couldn't mount storage... check to see if we have dual storage
1300 int has_dual_storage;
1301 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual_storage);
1302 if (has_dual_storage == 1) {
1303 // We have dual storage, see if we're using the internal storage that should always be present
1304 if (current_storage_path == DataManager::GetSettingsStoragePath()) {
Dees_Troyab10ee22012-09-21 14:27:30 -04001305 if (!FreeStorage->Is_Encrypted) {
1306 // Not able to use internal, so error!
1307 LOGE("Unable to mount internal storage.\n");
1308 }
Dees_Troy8170a922012-09-18 15:40:25 -04001309 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1310 } else {
1311 // We were using external, flip to internal
1312 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0);
1313 current_storage_path = DataManager::GetCurrentStoragePath();
1314 FreeStorage = Find_Partition_By_Path(current_storage_path);
1315 if (FreeStorage != NULL) {
1316 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1317 } else {
1318 LOGE("Unable to locate internal storage partition.\n");
1319 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1320 }
1321 }
1322 } else {
1323 // No dual storage and unable to mount storage, error!
1324 LOGE("Unable to mount storage.\n");
1325 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1326 }
1327 } else {
1328 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1329 }
1330 } else {
Dees_Troy51127312012-09-08 13:08:49 -04001331 LOGI("Unable to find storage partition '%s'.\n", current_storage_path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -04001332 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001333 if (!Write_Fstab())
1334 LOGE("Error creating fstab\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001335 return;
1336}
1337
1338int TWPartitionManager::Decrypt_Device(string Password) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001339#ifdef TW_INCLUDE_CRYPTO
1340 int ret_val, password_len;
1341 char crypto_blkdev[255], cPassword[255];
1342 size_t result;
1343
1344 property_set("ro.crypto.state", "encrypted");
1345#ifdef TW_INCLUDE_JB_CRYPTO
1346 // No extra flags needed
1347#else
1348 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
1349 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
1350 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
1351 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
1352 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
1353 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
a39552696ff55ce2013-01-08 16:14:56 +00001354
1355#ifdef CRYPTO_SD_FS_TYPE
1356 property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
1357 property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
1358 property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
Dees_Troy5bf43922012-09-07 16:07:55 -04001359#endif
a39552696ff55ce2013-01-08 16:14:56 +00001360
1361 property_set("rw.km_fips_status", "ready");
1362
1363#endif
1364
1365 // some samsung devices store "footer" on efs partition
1366 TWPartition *efs = Find_Partition_By_Path("/efs");
1367 if(efs && !efs->Is_Mounted())
1368 efs->Mount(false);
1369 else
1370 efs = 0;
1371#ifdef TW_EXTERNAL_STORAGE_PATH
Dees_Troy20c02c02013-01-10 14:14:10 +00001372#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
a39552696ff55ce2013-01-08 16:14:56 +00001373 TWPartition* sdcard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH));
Dees_Troy85f44ed2013-01-09 18:42:36 +00001374 if (sdcard && sdcard->Mount(false)) {
a39552696ff55ce2013-01-08 16:14:56 +00001375 property_set("ro.crypto.external_encrypted", "1");
1376 property_set("ro.crypto.external_blkdev", sdcard->Actual_Block_Device.c_str());
1377 } else {
1378 property_set("ro.crypto.external_encrypted", "0");
1379 }
1380#endif
Dees_Troy20c02c02013-01-10 14:14:10 +00001381#endif
a39552696ff55ce2013-01-08 16:14:56 +00001382
Dees_Troy5bf43922012-09-07 16:07:55 -04001383 strcpy(cPassword, Password.c_str());
a39552696ff55ce2013-01-08 16:14:56 +00001384 int pwret = cryptfs_check_passwd(cPassword);
1385
1386 if (pwret != 0) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001387 LOGE("Failed to decrypt data.\n");
1388 return -1;
1389 }
a39552696ff55ce2013-01-08 16:14:56 +00001390
1391 if(efs)
1392 efs->UnMount(false);
1393
Dees_Troy5bf43922012-09-07 16:07:55 -04001394 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
1395 if (strcmp(crypto_blkdev, "error") == 0) {
1396 LOGE("Error retrieving decrypted data block device.\n");
1397 } else {
1398 TWPartition* dat = Find_Partition_By_Path("/data");
1399 if (dat != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001400 DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Primary_Block_Device);
Dees_Troy5bf43922012-09-07 16:07:55 -04001401 DataManager::SetValue(TW_IS_DECRYPTED, 1);
1402 dat->Is_Decrypted = true;
1403 dat->Decrypted_Block_Device = crypto_blkdev;
Gary Peck82599a82012-11-21 16:23:12 -08001404 dat->Setup_File_System(false);
Dees_Troy32c8eb82012-09-11 15:28:06 -04001405 ui_print("Data successfully decrypted, new block device: '%s'\n", crypto_blkdev);
a39552696ff55ce2013-01-08 16:14:56 +00001406
1407#ifdef CRYPTO_SD_FS_TYPE
1408 char crypto_blkdev_sd[255];
1409 property_get("ro.crypto.sd_fs_crypto_blkdev", crypto_blkdev_sd, "error");
1410 if (strcmp(crypto_blkdev_sd, "error") == 0) {
1411 LOGE("Error retrieving decrypted data block device.\n");
Dees_Troyc8bafa12013-01-10 15:43:00 +00001412 } else if(TWPartition* emmc = Find_Partition_By_Path(EXPAND(TW_INTERNAL_STORAGE_PATH))){
a39552696ff55ce2013-01-08 16:14:56 +00001413 emmc->Is_Decrypted = true;
1414 emmc->Decrypted_Block_Device = crypto_blkdev_sd;
1415 emmc->Setup_File_System(false);
1416 ui_print("Internal SD successfully decrypted, new block device: '%s'\n", crypto_blkdev_sd);
1417 }
a39552696ff55ce2013-01-08 16:14:56 +00001418#endif //ifdef CRYPTO_SD_FS_TYPE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001419#ifdef TW_EXTERNAL_STORAGE_PATH
Dees_Troy20c02c02013-01-10 14:14:10 +00001420#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
Dees_Troy85f44ed2013-01-09 18:42:36 +00001421 char is_external_decrypted[255];
1422 property_get("ro.crypto.external_use_ecryptfs", is_external_decrypted, "0");
1423 if (strcmp(is_external_decrypted, "1") == 0) {
1424 sdcard->Is_Decrypted = true;
1425 sdcard->EcryptFS_Password = Password;
1426 sdcard->Decrypted_Block_Device = sdcard->Actual_Block_Device;
Dees_Troy999b39d2013-01-14 15:36:13 +00001427 string MetaEcfsFile = EXPAND(TW_EXTERNAL_STORAGE_PATH);
1428 MetaEcfsFile += "/.MetaEcfsFile";
1429 if (!TWFunc::Path_Exists(MetaEcfsFile)) {
1430 // External storage isn't actually encrypted so unmount and remount without ecryptfs
1431 sdcard->UnMount(false);
1432 sdcard->Mount(false);
1433 }
Dees_Troy85f44ed2013-01-09 18:42:36 +00001434 } else {
1435 sdcard->Is_Decrypted = false;
1436 sdcard->Decrypted_Block_Device = "";
1437 }
Dees_Troy20c02c02013-01-10 14:14:10 +00001438#endif
Dees_Troy85f44ed2013-01-09 18:42:36 +00001439#endif //ifdef TW_EXTERNAL_STORAGE_PATH
a39552696ff55ce2013-01-08 16:14:56 +00001440
Dees_Troy5bf43922012-09-07 16:07:55 -04001441 // Sleep for a bit so that the device will be ready
1442 sleep(1);
Dees_Troy16b74352012-11-14 22:27:31 +00001443#ifdef RECOVERY_SDCARD_ON_DATA
1444 if (dat->Mount(false) && TWFunc::Path_Exists("/data/media/0")) {
1445 dat->Storage_Path = "/data/media/0";
1446 dat->Symlink_Path = dat->Storage_Path;
1447 DataManager::SetValue(TW_INTERNAL_PATH, "/data/media/0");
1448 dat->UnMount(false);
1449 DataManager::SetBackupFolder();
Dees_Troydc8bc1b2013-01-17 01:39:28 +00001450 Output_Partition(dat);
Dees_Troy16b74352012-11-14 22:27:31 +00001451 }
1452#endif
Dees_Troy5bf43922012-09-07 16:07:55 -04001453 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -04001454 UnMount_Main_Partitions();
Dees_Troy5bf43922012-09-07 16:07:55 -04001455 } else
1456 LOGE("Unable to locate data partition.\n");
1457 }
1458 return 0;
1459#else
1460 LOGE("No crypto support was compiled into this build.\n");
1461 return -1;
1462#endif
Dees_Troy51a0e822012-09-05 15:24:24 -04001463 return 1;
Dees_Troy51127312012-09-08 13:08:49 -04001464}
1465
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001466int TWPartitionManager::Fix_Permissions(void) {
1467 int result = 0;
1468 if (!Mount_By_Path("/data", true))
1469 return false;
1470
1471 if (!Mount_By_Path("/system", true))
1472 return false;
1473
1474 Mount_By_Path("/sd-ext", false);
1475
1476 fixPermissions perms;
1477 result = perms.fixPerms(true, false);
Dees_Troy1a650e62012-10-19 20:54:32 -04001478 UnMount_Main_Partitions();
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001479 ui_print("Done.\n\n");
1480 return result;
1481}
1482
Dees_Troy8170a922012-09-18 15:40:25 -04001483//partial kangbang from system/vold
Dees_Troyd21618c2012-10-14 18:48:49 -04001484int TWPartitionManager::Open_Lun_File(string Partition_Path, string Lun_File) {
1485 int fd;
1486 TWPartition* Part = Find_Partition_By_Path(Partition_Path);
1487
1488 if (Part == NULL) {
1489 LOGE("Unable to locate volume information for USB storage mode.");
1490 return false;
1491 }
1492 if (!Part->UnMount(true))
1493 return false;
1494
1495 if ((fd = open(Lun_File.c_str(), O_WRONLY)) < 0) {
1496 LOGE("Unable to open ums lunfile '%s': (%s)\n", Lun_File.c_str(), strerror(errno));
1497 return false;
1498 }
1499
1500 if (write(fd, Part->Actual_Block_Device.c_str(), Part->Actual_Block_Device.size()) < 0) {
1501 LOGE("Unable to write to ums lunfile '%s': (%s)\n", Lun_File.c_str(), strerror(errno));
1502 close(fd);
1503 return false;
1504 }
1505 close(fd);
1506 return true;
1507}
1508
Dees_Troy8170a922012-09-18 15:40:25 -04001509int TWPartitionManager::usb_storage_enable(void) {
Dees_Troyd21618c2012-10-14 18:48:49 -04001510 int has_dual, has_data_media;
Dees_Troy8170a922012-09-18 15:40:25 -04001511 char lun_file[255];
Dees_Troy8170a922012-09-18 15:40:25 -04001512 string ext_path;
Dees_Troyd21618c2012-10-14 18:48:49 -04001513 bool has_multiple_lun = false;
Dees_Troy8170a922012-09-18 15:40:25 -04001514
1515 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual);
1516 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
1517 if (has_dual == 1 && has_data_media == 0) {
Dees_Troyd21618c2012-10-14 18:48:49 -04001518 string Lun_File_str = CUSTOM_LUN_FILE;
1519 size_t found = Lun_File_str.find("%");
1520 if (found != string::npos) {
1521 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
1522 if (TWFunc::Path_Exists(lun_file))
1523 has_multiple_lun = true;
1524 }
1525 if (!has_multiple_lun) {
Dees_Troyf4ca6122012-10-13 22:17:20 -04001526 // Device doesn't have multiple lun files, mount current storage
Dees_Troyf4ca6122012-10-13 22:17:20 -04001527 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001528 return Open_Lun_File(DataManager::GetCurrentStoragePath(), lun_file);
Dees_Troyf4ca6122012-10-13 22:17:20 -04001529 } else {
1530 // Device has multiple lun files
Dees_Troyf4ca6122012-10-13 22:17:20 -04001531 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001532 if (!Open_Lun_File(DataManager::GetSettingsStoragePath(), lun_file))
Dees_Troyf4ca6122012-10-13 22:17:20 -04001533 return false;
Dees_Troyf4ca6122012-10-13 22:17:20 -04001534 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
Dees_Troyf4ca6122012-10-13 22:17:20 -04001535 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
Dees_Troyd21618c2012-10-14 18:48:49 -04001536 return Open_Lun_File(ext_path, lun_file);
Dees_Troy8170a922012-09-18 15:40:25 -04001537 }
Dees_Troy8170a922012-09-18 15:40:25 -04001538 } else {
1539 if (has_data_media == 0)
1540 ext_path = DataManager::GetCurrentStoragePath();
1541 else
1542 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
Dees_Troy8170a922012-09-18 15:40:25 -04001543 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001544 return Open_Lun_File(ext_path, lun_file);
Dees_Troy8170a922012-09-18 15:40:25 -04001545 }
1546 return true;
1547}
1548
1549int TWPartitionManager::usb_storage_disable(void) {
1550 int fd, index;
1551 char lun_file[255];
1552
1553 for (index=0; index<2; index++) {
1554 sprintf(lun_file, CUSTOM_LUN_FILE, index);
1555
1556 if ((fd = open(lun_file, O_WRONLY)) < 0) {
Dees_Troye58d5262012-09-21 12:27:57 -04001557 Mount_All_Storage();
1558 Update_System_Details();
1559 if (index == 0) {
Dees_Troy8170a922012-09-18 15:40:25 -04001560 LOGE("Unable to open ums lunfile '%s': (%s)", lun_file, strerror(errno));
Dees_Troye58d5262012-09-21 12:27:57 -04001561 return false;
1562 } else
1563 return true;
Dees_Troy8170a922012-09-18 15:40:25 -04001564 }
1565
1566 char ch = 0;
1567 if (write(fd, &ch, 1) < 0) {
Dees_Troy8170a922012-09-18 15:40:25 -04001568 close(fd);
Dees_Troye58d5262012-09-21 12:27:57 -04001569 Mount_All_Storage();
1570 Update_System_Details();
1571 if (index == 0) {
1572 LOGE("Unable to write to ums lunfile '%s': (%s)", lun_file, strerror(errno));
1573 return false;
1574 } else
1575 return true;
Dees_Troy8170a922012-09-18 15:40:25 -04001576 }
1577
1578 close(fd);
1579 }
Dees_Troye58d5262012-09-21 12:27:57 -04001580 Mount_All_Storage();
1581 Update_System_Details();
Dees_Troycfd73ef2012-10-12 16:52:00 -04001582 UnMount_Main_Partitions();
Dees_Troy8170a922012-09-18 15:40:25 -04001583 return true;
Dees_Troy812660f2012-09-20 09:55:17 -04001584}
1585
1586void TWPartitionManager::Mount_All_Storage(void) {
1587 std::vector<TWPartition*>::iterator iter;
1588
1589 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1590 if ((*iter)->Is_Storage)
1591 (*iter)->Mount(false);
1592 }
Dees_Troy2c50e182012-09-26 20:05:28 -04001593}
Dees_Troy9350b8d2012-09-27 12:38:38 -04001594
Dees_Troyd0384ef2012-10-12 12:15:42 -04001595void TWPartitionManager::UnMount_Main_Partitions(void) {
1596 // Unmounts system and data if data is not data/media
1597 // Also unmounts boot if boot is mountable
1598 LOGI("Unmounting main partitions...\n");
1599
1600 TWPartition* Boot_Partition = Find_Partition_By_Path("/boot");
1601
1602 UnMount_By_Path("/system", true);
1603#ifndef RECOVERY_SDCARD_ON_DATA
1604 UnMount_By_Path("/data", true);
1605#endif
1606 if (Boot_Partition != NULL && Boot_Partition->Can_Be_Mounted)
1607 Boot_Partition->UnMount(true);
1608}
1609
Dees_Troy9350b8d2012-09-27 12:38:38 -04001610int TWPartitionManager::Partition_SDCard(void) {
1611 char mkdir_path[255], temp[255], line[512];
1612 string Command, Device, fat_str, ext_str, swap_str, start_loc, end_loc, ext_format, sd_path, tmpdevice;
1613 int ext, swap, total_size = 0, fat_size;
1614 FILE* fp;
1615
1616 ui_print("Partitioning SD Card...\n");
1617#ifdef TW_EXTERNAL_STORAGE_PATH
1618 TWPartition* SDCard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH));
1619#else
1620 TWPartition* SDCard = Find_Partition_By_Path("/sdcard");
1621#endif
1622 if (SDCard == NULL) {
1623 LOGE("Unable to locate device to partition.\n");
1624 return false;
1625 }
1626 if (!SDCard->UnMount(true))
1627 return false;
1628 TWPartition* SDext = Find_Partition_By_Path("/sd-ext");
1629 if (SDext != NULL) {
1630 if (!SDext->UnMount(true))
1631 return false;
1632 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001633 string result;
1634 TWFunc::Exec_Cmd("umount \"$SWAPPATH\"", result);
Dees_Troy9350b8d2012-09-27 12:38:38 -04001635 Device = SDCard->Actual_Block_Device;
1636 // Just use the root block device
1637 Device.resize(strlen("/dev/block/mmcblkX"));
1638
1639 // Find the size of the block device:
1640 fp = fopen("/proc/partitions", "rt");
1641 if (fp == NULL) {
1642 LOGE("Unable to open /proc/partitions\n");
1643 return false;
1644 }
1645
1646 while (fgets(line, sizeof(line), fp) != NULL)
1647 {
1648 unsigned long major, minor, blocks;
1649 char device[512];
1650 char tmpString[64];
1651
1652 if (strlen(line) < 7 || line[0] == 'm') continue;
1653 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
1654
1655 tmpdevice = "/dev/block/";
1656 tmpdevice += device;
1657 if (tmpdevice == Device) {
1658 // Adjust block size to byte size
1659 total_size = (int)(blocks * 1024ULL / 1000000LLU);
1660 break;
1661 }
1662 }
1663 fclose(fp);
1664
1665 DataManager::GetValue("tw_sdext_size", ext);
1666 DataManager::GetValue("tw_swap_size", swap);
1667 DataManager::GetValue("tw_sdpart_file_system", ext_format);
1668 fat_size = total_size - ext - swap;
1669 LOGI("sd card block device is '%s', sdcard size is: %iMB, fat size: %iMB, ext size: %iMB, ext system: '%s', swap size: %iMB\n", Device.c_str(), total_size, fat_size, ext, ext_format.c_str(), swap);
1670 memset(temp, 0, sizeof(temp));
1671 sprintf(temp, "%i", fat_size);
1672 fat_str = temp;
1673 memset(temp, 0, sizeof(temp));
1674 sprintf(temp, "%i", fat_size + ext);
1675 ext_str = temp;
1676 memset(temp, 0, sizeof(temp));
1677 sprintf(temp, "%i", fat_size + ext + swap);
1678 swap_str = temp;
1679 if (ext + swap > total_size) {
1680 LOGE("EXT + Swap size is larger than sdcard size.\n");
1681 return false;
1682 }
1683 ui_print("Removing partition table...\n");
1684 Command = "parted -s " + Device + " mklabel msdos";
1685 LOGI("Command is: '%s'\n", Command.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001686 if (TWFunc::Exec_Cmd(Command, result) != 0) {
Dees_Troy9350b8d2012-09-27 12:38:38 -04001687 LOGE("Unable to remove partition table.\n");
1688 Update_System_Details();
1689 return false;
1690 }
1691 ui_print("Creating FAT32 partition...\n");
1692 Command = "parted " + Device + " mkpartfs primary fat32 0 " + fat_str + "MB";
1693 LOGI("Command is: '%s'\n", Command.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001694 if (TWFunc::Exec_Cmd(Command, result) != 0) {
Dees_Troy9350b8d2012-09-27 12:38:38 -04001695 LOGE("Unable to create FAT32 partition.\n");
1696 return false;
1697 }
1698 if (ext > 0) {
1699 ui_print("Creating EXT partition...\n");
1700 Command = "parted " + Device + " mkpartfs primary ext2 " + fat_str + "MB " + ext_str + "MB";
1701 LOGI("Command is: '%s'\n", Command.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001702 if (TWFunc::Exec_Cmd(Command, result) != 0) {
Dees_Troy9350b8d2012-09-27 12:38:38 -04001703 LOGE("Unable to create EXT partition.\n");
1704 Update_System_Details();
1705 return false;
1706 }
1707 }
1708 if (swap > 0) {
1709 ui_print("Creating swap partition...\n");
1710 Command = "parted " + Device + " mkpartfs primary linux-swap " + ext_str + "MB " + swap_str + "MB";
1711 LOGI("Command is: '%s'\n", Command.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001712 if (TWFunc::Exec_Cmd(Command, result) != 0) {
Dees_Troy9350b8d2012-09-27 12:38:38 -04001713 LOGE("Unable to create swap partition.\n");
1714 Update_System_Details();
1715 return false;
1716 }
1717 }
1718 // recreate TWRP folder and rewrite settings - these will be gone after sdcard is partitioned
1719#ifdef TW_EXTERNAL_STORAGE_PATH
1720 Mount_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1);
1721 DataManager::GetValue(TW_EXTERNAL_PATH, sd_path);
1722 memset(mkdir_path, 0, sizeof(mkdir_path));
1723 sprintf(mkdir_path, "%s/TWRP", sd_path.c_str());
1724#else
1725 Mount_By_Path("/sdcard", 1);
1726 strcpy(mkdir_path, "/sdcard/TWRP");
1727#endif
1728 mkdir(mkdir_path, 0777);
1729 DataManager::Flush();
1730#ifdef TW_EXTERNAL_STORAGE_PATH
1731 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1732 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1733 DataManager::SetValue(TW_ZIP_LOCATION_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1734#else
1735 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, "/sdcard");
1736 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1737 DataManager::SetValue(TW_ZIP_LOCATION_VAR, "/sdcard");
1738#endif
1739 if (ext > 0) {
1740 if (SDext == NULL) {
1741 LOGE("Unable to locate sd-ext partition.\n");
1742 return false;
1743 }
1744 Command = "mke2fs -t " + ext_format + " -m 0 " + SDext->Actual_Block_Device;
1745 ui_print("Formatting sd-ext as %s...\n", ext_format.c_str());
1746 LOGI("Formatting sd-ext after partitioning, command: '%s'\n", Command.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001747 TWFunc::Exec_Cmd(Command, result);
Dees_Troy9350b8d2012-09-27 12:38:38 -04001748 }
1749
1750 Update_System_Details();
1751 ui_print("Partitioning complete.\n");
1752 return true;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001753}
Dees_Troya13d74f2013-03-24 08:54:55 -05001754
1755void TWPartitionManager::Get_Partition_List(string ListType, std::vector<PartitionList> *Partition_List) {
1756 std::vector<TWPartition*>::iterator iter;
1757 if (ListType == "mount") {
1758 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1759 if ((*iter)->Can_Be_Mounted && !(*iter)->Is_SubPartition) {
1760 struct PartitionList part;
1761 part.Display_Name = (*iter)->Display_Name;
1762 part.Mount_Point = (*iter)->Mount_Point;
1763 part.selected = (*iter)->Is_Mounted();
1764 Partition_List->push_back(part);
1765 }
1766 }
1767 } else if (ListType == "storage") {
1768 char free_space[255];
1769 string Current_Storage = DataManager::GetCurrentStoragePath();
1770 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1771 if ((*iter)->Is_Storage) {
1772 struct PartitionList part;
1773 sprintf(free_space, "%llu", (*iter)->Free / 1024 / 1024);
1774 part.Display_Name = (*iter)->Storage_Name + " (";
1775 part.Display_Name += free_space;
1776 part.Display_Name += "MB)";
1777 part.Mount_Point = (*iter)->Storage_Path;
1778 if ((*iter)->Storage_Path == Current_Storage)
1779 part.selected = 1;
1780 else
1781 part.selected = 0;
1782 Partition_List->push_back(part);
1783 }
1784 }
1785 } else if (ListType == "backup") {
1786 char backup_size[255];
1787 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1788 if ((*iter)->Can_Be_Backed_Up && !(*iter)->Is_SubPartition) {
1789 struct PartitionList part;
1790 sprintf(backup_size, "%llu", (*iter)->Backup_Size / 1024 / 1024);
1791 part.Display_Name = (*iter)->Backup_Display_Name + " (";
1792 part.Display_Name += backup_size;
1793 part.Display_Name += "MB)";
1794 part.Mount_Point = (*iter)->Backup_Path;
1795 part.selected = 0;
1796 Partition_List->push_back(part);
1797 }
1798 }
1799 } else if (ListType == "restore") {
1800 string Restore_List, restore_path;
1801 TWPartition* restore_part = NULL;
1802
1803 DataManager::GetValue("tw_restore_list", Restore_List);
1804 if (!Restore_List.empty()) {
1805 size_t start_pos = 0, end_pos = Restore_List.find(";", start_pos);
1806 while (end_pos != string::npos && start_pos < Restore_List.size()) {
1807 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
1808 if ((restore_part = Find_Partition_By_Path(restore_path)) != NULL && !restore_part->Is_SubPartition) {
1809 if (restore_part->Backup_Name == "recovery") {
1810 // Don't allow restore of recovery (causes problems on some devices)
1811 } else {
1812 struct PartitionList part;
1813 part.Display_Name = restore_part->Backup_Display_Name;
1814 part.Mount_Point = restore_part->Backup_Path;
1815 part.selected = 1;
1816 Partition_List->push_back(part);
1817 }
1818 } else {
1819 LOGE("Unable to locate '%s' partition for restore.\n", restore_path.c_str());
1820 }
1821 start_pos = end_pos + 1;
1822 end_pos = Restore_List.find(";", start_pos);
1823 }
1824 }
1825 } else if (ListType == "wipe") {
1826 struct PartitionList dalvik;
1827 dalvik.Display_Name = "Dalvik Cache";
1828 dalvik.Mount_Point = "DALVIK";
1829 dalvik.selected = 0;
1830 Partition_List->push_back(dalvik);
1831 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1832 if ((*iter)->Wipe_Available_in_GUI && !(*iter)->Is_SubPartition) {
1833 struct PartitionList part;
1834 part.Display_Name = (*iter)->Display_Name;
1835 part.Mount_Point = (*iter)->Mount_Point;
1836 part.selected = 0;
1837 Partition_List->push_back(part);
1838 }
1839 if ((*iter)->Has_Android_Secure) {
1840 struct PartitionList part;
1841 part.Display_Name = (*iter)->Backup_Display_Name;
1842 part.Mount_Point = (*iter)->Backup_Path;
1843 part.selected = 0;
1844 Partition_List->push_back(part);
1845 }
1846 }
1847 } else {
1848 LOGE("Unknown list type '%s' requested for TWPartitionManager::Get_Partition_List\n", ListType.c_str());
1849 }
1850}
1851
1852int TWPartitionManager::Fstab_Processed(void) {
1853 return Partitions.size();
1854}