blob: b3c6adc36dc26403f1dd30aceeb89c9707fee228 [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>
Dees_Troy51a0e822012-09-05 15:24:24 -040034
35#include "variables.h"
36#include "common.h"
Dees_Troy093b7642012-09-21 15:59:38 -040037#include "ui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040038#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040039#include "data.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040040#include "twrp-functions.hpp"
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -040041#include "fixPermissions.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040042
Dees_Troy5bf43922012-09-07 16:07:55 -040043#ifdef TW_INCLUDE_CRYPTO
44 #ifdef TW_INCLUDE_JB_CRYPTO
45 #include "crypto/jb/cryptfs.h"
46 #else
47 #include "crypto/ics/cryptfs.h"
48 #endif
49 #include "cutils/properties.h"
50#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040051
Dees_Troy093b7642012-09-21 15:59:38 -040052extern RecoveryUI* ui;
53
Dees_Troy51a0e822012-09-05 15:24:24 -040054int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -040055 FILE *fstabFile;
56 char fstab_line[MAX_FSTAB_LINE_LENGTH];
57
58 fstabFile = fopen(Fstab_Filename.c_str(), "rt");
59 if (fstabFile == NULL) {
60 LOGE("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str());
61 return false;
62 }
63
64 while (fgets(fstab_line, sizeof(fstab_line), fstabFile) != NULL) {
65 if (fstab_line[0] != '/')
66 continue;
67
Dees_Troy2a923582012-09-20 12:13:34 -040068 if (fstab_line[strlen(fstab_line) - 1] != '\n')
69 fstab_line[strlen(fstab_line)] = '\n';
70
Dees_Troy5bf43922012-09-07 16:07:55 -040071 TWPartition* partition = new TWPartition();
Dees_Troy2a923582012-09-20 12:13:34 -040072 string line = fstab_line;
Dees_Troyab10ee22012-09-21 14:27:30 -040073 memset(fstab_line, 0, sizeof(fstab_line));
Dees_Troy2a923582012-09-20 12:13:34 -040074
Dees_Troy5bf43922012-09-07 16:07:55 -040075 if (partition->Process_Fstab_Line(line, Display_Error)) {
76 Partitions.push_back(partition);
77 } else {
78 delete partition;
79 }
80 }
81 fclose(fstabFile);
82 if (!Write_Fstab()) {
83 if (Display_Error)
84 LOGE("Error creating fstab\n");
85 else
86 LOGI("Error creating fstab\n");
87 }
Dees_Troy51127312012-09-08 13:08:49 -040088 Update_System_Details();
Dees_Troy5bf43922012-09-07 16:07:55 -040089 return true;
90}
91
92int TWPartitionManager::Write_Fstab(void) {
93 FILE *fp;
94 std::vector<TWPartition*>::iterator iter;
95 string Line;
96
97 fp = fopen("/etc/fstab", "w");
98 if (fp == NULL) {
Dees_Troy63c8df72012-09-10 14:02:05 -040099 LOGI("Can not open /etc/fstab.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400100 return false;
101 }
Dees_Troy63c8df72012-09-10 14:02:05 -0400102 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -0400103 if ((*iter)->Can_Be_Mounted) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400104 Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
Dees_Troy5bf43922012-09-07 16:07:55 -0400105 fputs(Line.c_str(), fp);
Dees_Troy51127312012-09-08 13:08:49 -0400106 // Handle subpartition tracking
107 if ((*iter)->Is_SubPartition) {
108 TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
109 if (ParentPartition)
110 ParentPartition->Has_SubPartition = true;
111 else
112 LOGE("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
113 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400114 }
115 }
116 fclose(fp);
117 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400118}
119
Dees_Troy8170a922012-09-18 15:40:25 -0400120void TWPartitionManager::Output_Partition_Logging(void) {
121 std::vector<TWPartition*>::iterator iter;
122
123 printf("\n\nPartition Logs:\n");
124 for (iter = Partitions.begin(); iter != Partitions.end(); iter++)
125 Output_Partition((*iter));
126}
127
128void TWPartitionManager::Output_Partition(TWPartition* Part) {
129 unsigned long long mb = 1048576;
130
131 if (Part->Can_Be_Mounted) {
132 printf("%s | %s | Size: %iMB Used: %iMB Free: %iMB Backup Size: %iMB\n Flags: ", Part->Mount_Point.c_str(), Part->Actual_Block_Device.c_str(), (int)(Part->Size / mb), (int)(Part->Used / mb), (int)(Part->Free / mb), (int)(Part->Backup_Size / mb));
133 if (Part->Can_Be_Wiped)
134 printf("Can_Be_Wiped ");
135 if (Part->Wipe_During_Factory_Reset)
136 printf("Wipe_During_Factory_Reset ");
137 if (Part->Wipe_Available_in_GUI)
138 printf("Wipe_Available_in_GUI ");
139 if (Part->Is_SubPartition)
140 printf("Is_SubPartition ");
141 if (Part->Has_SubPartition)
142 printf("Has_SubPartition ");
143 if (Part->Removable)
144 printf("Removable ");
145 if (Part->Is_Present)
146 printf("IsPresent ");
147 if (Part->Can_Be_Encrypted)
148 printf("Can_Be_Encrypted ");
149 if (Part->Is_Encrypted)
150 printf("Is_Encrypted ");
151 if (Part->Is_Decrypted)
152 printf("Is_Decrypted ");
153 if (Part->Has_Data_Media)
154 printf("Has_Data_Media ");
Dees_Troye58d5262012-09-21 12:27:57 -0400155 if (Part->Has_Android_Secure)
156 printf("Has_Android_Secure ");
Dees_Troy8170a922012-09-18 15:40:25 -0400157 if (Part->Is_Storage)
158 printf("Is_Storage ");
159 printf("\n");
160 if (!Part->SubPartition_Of.empty())
161 printf(" SubPartition_Of: %s\n", Part->SubPartition_Of.c_str());
162 if (!Part->Symlink_Path.empty())
163 printf(" Symlink_Path: %s\n", Part->Symlink_Path.c_str());
164 if (!Part->Symlink_Mount_Point.empty())
165 printf(" Symlink_Mount_Point: %s\n", Part->Symlink_Mount_Point.c_str());
166 if (!Part->Primary_Block_Device.empty())
167 printf(" Primary_Block_Device: %s\n", Part->Primary_Block_Device.c_str());
168 if (!Part->Alternate_Block_Device.empty())
169 printf(" Alternate_Block_Device: %s\n", Part->Alternate_Block_Device.c_str());
170 if (!Part->Decrypted_Block_Device.empty())
171 printf(" Decrypted_Block_Device: %s\n", Part->Decrypted_Block_Device.c_str());
172 if (Part->Length != 0)
173 printf(" Length: %i\n", Part->Length);
174 if (!Part->Display_Name.empty())
175 printf(" Display_Name: %s\n", Part->Display_Name.c_str());
Dees_Troye58d5262012-09-21 12:27:57 -0400176 if (!Part->Backup_Path.empty())
177 printf(" Backup_Path: %s\n", Part->Backup_Path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400178 if (!Part->Backup_Name.empty())
179 printf(" Backup_Name: %s\n", Part->Backup_Name.c_str());
180 if (!Part->Backup_FileName.empty())
181 printf(" Backup_FileName: %s\n", Part->Backup_FileName.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400182 if (!Part->Storage_Path.empty())
183 printf(" Storage_Path: %s\n", Part->Storage_Path.c_str());
184 if (!Part->Current_File_System.empty())
185 printf(" Current_File_System: %s\n", Part->Current_File_System.c_str());
186 if (!Part->Fstab_File_System.empty())
187 printf(" Fstab_File_System: %s\n", Part->Fstab_File_System.c_str());
188 if (Part->Format_Block_Size != 0)
189 printf(" Format_Block_Size: %i\n", Part->Format_Block_Size);
190 } else {
191 printf("%s | %s | Size: %iMB\n", Part->Mount_Point.c_str(), Part->Actual_Block_Device.c_str(), (int)(Part->Size / mb));
192 }
Dees_Troy094207a2012-09-26 12:00:39 -0400193 if (!Part->MTD_Name.empty())
194 printf(" MTD_Name: %s\n", Part->MTD_Name.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400195 string back_meth = Part->Backup_Method_By_Name();
196 printf(" Backup_Method: %s\n\n", back_meth.c_str());
197}
198
Dees_Troy51a0e822012-09-05 15:24:24 -0400199int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400200 std::vector<TWPartition*>::iterator iter;
201 int ret = false;
202 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400203 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400204
Dees_Troy43d8b002012-09-17 16:00:01 -0400205 if (Local_Path == "/tmp")
206 return true;
207
Dees_Troy5bf43922012-09-07 16:07:55 -0400208 // Iterate through all partitions
209 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400210 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400211 ret = (*iter)->Mount(Display_Error);
212 found = true;
Dees_Troy51127312012-09-08 13:08:49 -0400213 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400214 (*iter)->Mount(Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400215 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400216 }
217 if (found) {
218 return ret;
219 } else if (Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400220 LOGE("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400221 } else {
Dees_Troy51127312012-09-08 13:08:49 -0400222 LOGI("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400223 }
224 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400225}
226
227int TWPartitionManager::Mount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400228 TWPartition* Part = Find_Partition_By_Block(Block);
Dees_Troy5bf43922012-09-07 16:07:55 -0400229
Dees_Troy51127312012-09-08 13:08:49 -0400230 if (Part) {
231 if (Part->Has_SubPartition) {
232 std::vector<TWPartition*>::iterator subpart;
233
234 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
235 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
236 (*subpart)->Mount(Display_Error);
237 }
238 return Part->Mount(Display_Error);
239 } else
240 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400241 }
242 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400243 LOGE("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400244 else
Dees_Troy51127312012-09-08 13:08:49 -0400245 LOGI("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400246 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400247}
248
249int TWPartitionManager::Mount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400250 TWPartition* Part = Find_Partition_By_Name(Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400251
Dees_Troy51127312012-09-08 13:08:49 -0400252 if (Part) {
253 if (Part->Has_SubPartition) {
254 std::vector<TWPartition*>::iterator subpart;
255
256 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
257 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
258 (*subpart)->Mount(Display_Error);
259 }
260 return Part->Mount(Display_Error);
261 } else
262 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400263 }
264 if (Display_Error)
Dees_Troy51127312012-09-08 13:08:49 -0400265 LOGE("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400266 else
Dees_Troy51127312012-09-08 13:08:49 -0400267 LOGI("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400268 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400269}
270
271int TWPartitionManager::UnMount_By_Path(string Path, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400272 std::vector<TWPartition*>::iterator iter;
273 int ret = false;
274 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400275 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy51127312012-09-08 13:08:49 -0400276
277 // Iterate through all partitions
278 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400279 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400280 ret = (*iter)->UnMount(Display_Error);
281 found = true;
282 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
283 (*iter)->UnMount(Display_Error);
284 }
285 }
286 if (found) {
287 return ret;
288 } else if (Display_Error) {
289 LOGE("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
290 } else {
291 LOGI("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
292 }
293 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400294}
295
296int TWPartitionManager::UnMount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400297 TWPartition* Part = Find_Partition_By_Block(Block);
298
299 if (Part) {
300 if (Part->Has_SubPartition) {
301 std::vector<TWPartition*>::iterator subpart;
302
303 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
304 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
305 (*subpart)->UnMount(Display_Error);
306 }
307 return Part->UnMount(Display_Error);
308 } else
309 return Part->UnMount(Display_Error);
310 }
311 if (Display_Error)
312 LOGE("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
313 else
314 LOGI("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
315 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400316}
317
318int TWPartitionManager::UnMount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400319 TWPartition* Part = Find_Partition_By_Name(Name);
320
321 if (Part) {
322 if (Part->Has_SubPartition) {
323 std::vector<TWPartition*>::iterator subpart;
324
325 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
326 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
327 (*subpart)->UnMount(Display_Error);
328 }
329 return Part->UnMount(Display_Error);
330 } else
331 return Part->UnMount(Display_Error);
332 }
333 if (Display_Error)
334 LOGE("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
335 else
336 LOGI("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
337 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400338}
339
340int TWPartitionManager::Is_Mounted_By_Path(string Path) {
Dees_Troy51127312012-09-08 13:08:49 -0400341 TWPartition* Part = Find_Partition_By_Path(Path);
342
343 if (Part)
344 return Part->Is_Mounted();
345 else
346 LOGI("Is_Mounted: Unable to find partition for path '%s'\n", Path.c_str());
347 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400348}
349
350int TWPartitionManager::Is_Mounted_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400351 TWPartition* Part = Find_Partition_By_Block(Block);
352
353 if (Part)
354 return Part->Is_Mounted();
355 else
356 LOGI("Is_Mounted: 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::Is_Mounted_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400361 TWPartition* Part = Find_Partition_By_Name(Name);
362
363 if (Part)
364 return Part->Is_Mounted();
365 else
366 LOGI("Is_Mounted: Unable to find partition for name '%s'\n", Name.c_str());
367 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400368}
369
Dees_Troy5bf43922012-09-07 16:07:55 -0400370int TWPartitionManager::Mount_Current_Storage(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400371 string current_storage_path = DataManager::GetCurrentStoragePath();
372
373 if (Mount_By_Path(current_storage_path, Display_Error)) {
374 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
375 if (FreeStorage)
376 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
377 return true;
378 }
379 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400380}
381
Dees_Troy5bf43922012-09-07 16:07:55 -0400382int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) {
383 return Mount_By_Path(DataManager::GetSettingsStoragePath(), Display_Error);
384}
385
386TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) {
387 std::vector<TWPartition*>::iterator iter;
Dees_Troy38bd7602012-09-14 13:33:53 -0400388 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400389
390 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400391 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path))
Dees_Troy5bf43922012-09-07 16:07:55 -0400392 return (*iter);
393 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400394 return NULL;
395}
396
Dees_Troy5bf43922012-09-07 16:07:55 -0400397TWPartition* TWPartitionManager::Find_Partition_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400398 std::vector<TWPartition*>::iterator iter;
399
400 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400401 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 -0400402 return (*iter);
403 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400404 return NULL;
Dees_Troy5bf43922012-09-07 16:07:55 -0400405}
406
407TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400408 std::vector<TWPartition*>::iterator iter;
409
410 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
411 if ((*iter)->Display_Name == Name)
412 return (*iter);
413 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400414 return NULL;
415}
Dees_Troy51a0e822012-09-05 15:24:24 -0400416
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400417int TWPartitionManager::Check_Backup_Name(bool Display_Error) {
418 // Check the backup name to ensure that it is the correct size and contains only valid characters
419 // and that a backup with that name doesn't already exist
420 char backup_name[MAX_BACKUP_NAME_LEN];
421 char backup_loc[255], tw_image_dir[255];
422 int copy_size;
423 int index, cur_char;
424 string Backup_Name, Backup_Loc;
425
426 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
427 copy_size = Backup_Name.size();
428 // Check size
429 if (copy_size > MAX_BACKUP_NAME_LEN) {
430 if (Display_Error)
431 LOGE("Backup name is too long.\n");
432 return -2;
433 }
434
435 // Check each character
436 strncpy(backup_name, Backup_Name.c_str(), copy_size);
437 if (strcmp(backup_name, "0") == 0)
438 return 0; // A "0" (zero) means to use the current timestamp for the backup name
439 for (index=0; index<copy_size; index++) {
440 cur_char = (int)backup_name[index];
441 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) {
442 // These are valid characters
443 // Numbers
444 // Upper case letters
445 // Lower case letters
446 // Space
447 // and -_.{}[]
448 } else {
449 if (Display_Error)
450 LOGE("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
451 return -3;
452 }
453 }
454
455 // Check to make sure that a backup with this name doesn't already exist
456 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Loc);
457 strcpy(backup_loc, Backup_Loc.c_str());
458 sprintf(tw_image_dir,"%s/%s/.", backup_loc, backup_name);
459 if (TWFunc::Path_Exists(tw_image_dir)) {
460 if (Display_Error)
461 LOGE("A backup with this name already exists.\n");
462 return -4;
463 }
464
465 // No problems found, return 0
466 return 0;
467}
468
Dees_Troy43d8b002012-09-17 16:00:01 -0400469bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename)
470{
471 char command[512];
472 string Full_File = Backup_Folder + Backup_Filename;
473
Dees_Troy4a2a1262012-09-18 09:33:47 -0400474 if (!generate_md5)
Dees_Troy43d8b002012-09-17 16:00:01 -0400475 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -0400476
Dees_Troyb46a6842012-09-25 11:06:46 -0400477 TWFunc::GUI_Operation_Text(TW_GENERATE_MD5_TEXT, "Generating MD5");
Dees_Troyc51f1f92012-09-20 15:32:13 -0400478 ui_print(" * Generating md5...\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400479
480 if (TWFunc::Path_Exists(Full_File)) {
481 sprintf(command, "cd '%s' && md5sum %s > %s.md5",Backup_Folder.c_str(), Backup_Filename.c_str(), Backup_Filename.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400482 if (system(command) == 0) {
Dees_Troyc5865ab2012-09-24 15:08:04 -0400483 ui_print(" * MD5 Created.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400484 return true;
485 } else {
Dees_Troyc5865ab2012-09-24 15:08:04 -0400486 ui_print(" * MD5 Error!\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400487 return false;
488 }
489 } else {
490 char filename[512];
491 int index = 0;
492
493 sprintf(filename, "%s%03i", Full_File.c_str(), index);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400494 while (TWFunc::Path_Exists(filename) == true) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400495 sprintf(command, "cd '%s' && md5sum %s%03i > %s%03i.md5",Backup_Folder.c_str(), Backup_Filename.c_str(), index, Backup_Filename.c_str(), index);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400496 if (system(command) != 0) {
Dees_Troyc5865ab2012-09-24 15:08:04 -0400497 ui_print(" * MD5 Error.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400498 return false;
499 }
500 index++;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400501 sprintf(filename, "%s%03i", Full_File.c_str(), index);
Dees_Troy43d8b002012-09-17 16:00:01 -0400502 }
503 if (index == 0) {
504 LOGE("Backup file: '%s' not found!\n", filename);
505 return false;
506 }
Dees_Troyc5865ab2012-09-24 15:08:04 -0400507 ui_print(" * MD5 Created.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400508 }
509 return true;
510}
511
Dees_Troy093b7642012-09-21 15:59:38 -0400512bool 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 -0400513 time_t start, stop;
Dees_Troy093b7642012-09-21 15:59:38 -0400514 int img_bps, file_bps;
515 unsigned long total_time, remain_time, section_time;
516 int use_compression, backup_time;
517 float pos;
Dees_Troy43d8b002012-09-17 16:00:01 -0400518
519 if (Part == NULL)
520 return true;
521
Dees_Troy093b7642012-09-21 15:59:38 -0400522 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
523
524 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
525 if (use_compression)
526 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
527 else
528 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
529
530 // We know the speed for both, how far into the whole backup are we, based on time
531 total_time = (*img_bytes / (unsigned long)img_bps) + (*file_bytes / (unsigned long)file_bps);
532 remain_time = (*img_bytes_remaining / (unsigned long)img_bps) + (*file_bytes_remaining / (unsigned long)file_bps);
533
534 pos = (total_time - remain_time) / (float) total_time;
535 ui->SetProgress(pos);
536
537 LOGI("Estimated Total time: %lu Estimated remaining time: %lu\n", total_time, remain_time);
538
539 // And get the time
540 if (Part->Backup_Method == 1)
541 section_time = Part->Backup_Size / file_bps;
542 else
543 section_time = Part->Backup_Size / img_bps;
544
545 // Set the position
546 pos = section_time / (float) total_time;
547 ui->ShowProgress(pos, section_time);
548
Dees_Troy43d8b002012-09-17 16:00:01 -0400549 time(&start);
550
551 if (Part->Backup(Backup_Folder)) {
Dees_Troy8170a922012-09-18 15:40:25 -0400552 if (Part->Has_SubPartition) {
553 std::vector<TWPartition*>::iterator subpart;
554
555 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
556 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
557 if (!(*subpart)->Backup(Backup_Folder))
558 return false;
559 if (!Make_MD5(generate_md5, Backup_Folder, (*subpart)->Backup_FileName))
560 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400561 if (Part->Backup_Method == 1) {
562 *file_bytes_remaining -= (*subpart)->Backup_Size;
563 } else {
564 *img_bytes_remaining -= (*subpart)->Backup_Size;
565 }
Dees_Troy8170a922012-09-18 15:40:25 -0400566 }
567 }
568 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400569 time(&stop);
Dees_Troy093b7642012-09-21 15:59:38 -0400570 backup_time = (int) difftime(stop, start);
571 LOGI("Partition Backup time: %d\n", backup_time);
Dees_Troy43d8b002012-09-17 16:00:01 -0400572 if (Part->Backup_Method == 1) {
573 *file_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400574 *file_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400575 } else {
576 *img_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400577 *img_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400578 }
579 return Make_MD5(generate_md5, Backup_Folder, Part->Backup_FileName);
580 } else {
581 return false;
582 }
583}
584
585int TWPartitionManager::Run_Backup(void) {
586 int check, do_md5, partition_count = 0;
587 string Backup_Folder, Backup_Name, Full_Backup_Path;
Dees_Troy8170a922012-09-18 15:40:25 -0400588 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 -0400589 unsigned long img_time = 0, file_time = 0;
590 TWPartition* backup_sys = NULL;
591 TWPartition* backup_data = NULL;
592 TWPartition* backup_cache = NULL;
593 TWPartition* backup_recovery = NULL;
594 TWPartition* backup_boot = NULL;
595 TWPartition* backup_andsec = NULL;
596 TWPartition* backup_sdext = NULL;
597 TWPartition* backup_sp1 = NULL;
598 TWPartition* backup_sp2 = NULL;
599 TWPartition* backup_sp3 = NULL;
600 TWPartition* storage = NULL;
Dees_Troy8170a922012-09-18 15:40:25 -0400601 std::vector<TWPartition*>::iterator subpart;
Dees_Troy43d8b002012-09-17 16:00:01 -0400602 struct tm *t;
603 time_t start, stop, seconds, total_start, total_stop;
604 seconds = time(0);
605 t = localtime(&seconds);
606
607 time(&total_start);
608
609 Update_System_Details();
610
611 if (!Mount_Current_Storage(true))
612 return false;
613
614 DataManager::GetValue(TW_SKIP_MD5_GENERATE_VAR, do_md5);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400615 if (do_md5 == 0)
Dees_Troy43d8b002012-09-17 16:00:01 -0400616 do_md5 = true;
Dees_Troyc5865ab2012-09-24 15:08:04 -0400617 else
618 do_md5 = false;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400619
Dees_Troy43d8b002012-09-17 16:00:01 -0400620 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Folder);
621 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400622 if (Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name.empty()) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400623 char timestamp[255];
624 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);
625 Backup_Name = timestamp;
626 }
627 LOGI("Backup Name is: '%s'\n", Backup_Name.c_str());
628 Full_Backup_Path = Backup_Folder + "/" + Backup_Name + "/";
629 LOGI("Full_Backup_Path is: '%s'\n", Full_Backup_Path.c_str());
630
631 ui_print("\n[BACKUP STARTED]\n");
632 ui_print(" * Backup Folder: %s\n", Full_Backup_Path.c_str());
633 if (!TWFunc::Recursive_Mkdir(Full_Backup_Path)) {
634 LOGE("Failed to make backup folder.\n");
635 return false;
636 }
637
638 LOGI("Calculating backup details...\n");
639 DataManager::GetValue(TW_BACKUP_SYSTEM_VAR, check);
640 if (check) {
641 backup_sys = Find_Partition_By_Path("/system");
642 if (backup_sys != NULL) {
643 partition_count++;
644 if (backup_sys->Backup_Method == 1)
645 file_bytes += backup_sys->Backup_Size;
646 else
647 img_bytes += backup_sys->Backup_Size;
648 } else {
649 LOGE("Unable to locate system partition.\n");
650 return false;
651 }
652 }
653 DataManager::GetValue(TW_BACKUP_DATA_VAR, check);
654 if (check) {
655 backup_data = Find_Partition_By_Path("/data");
656 if (backup_data != NULL) {
657 partition_count++;
Dees_Troy8170a922012-09-18 15:40:25 -0400658 subpart_size = 0;
659 if (backup_data->Has_SubPartition) {
660 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
661 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == backup_data->Mount_Point)
662 subpart_size += (*subpart)->Backup_Size;
663 }
664 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400665 if (backup_data->Backup_Method == 1)
Dees_Troy8170a922012-09-18 15:40:25 -0400666 file_bytes += backup_data->Backup_Size + subpart_size;
Dees_Troy43d8b002012-09-17 16:00:01 -0400667 else
Dees_Troy8170a922012-09-18 15:40:25 -0400668 img_bytes += backup_data->Backup_Size + subpart_size;
Dees_Troy43d8b002012-09-17 16:00:01 -0400669 } else {
670 LOGE("Unable to locate data partition.\n");
671 return false;
672 }
673 }
674 DataManager::GetValue(TW_BACKUP_CACHE_VAR, check);
675 if (check) {
676 backup_cache = Find_Partition_By_Path("/cache");
677 if (backup_cache != NULL) {
678 partition_count++;
679 if (backup_cache->Backup_Method == 1)
680 file_bytes += backup_cache->Backup_Size;
681 else
682 img_bytes += backup_cache->Backup_Size;
683 } else {
684 LOGE("Unable to locate cache partition.\n");
685 return false;
686 }
687 }
688 DataManager::GetValue(TW_BACKUP_RECOVERY_VAR, check);
689 if (check) {
690 backup_recovery = Find_Partition_By_Path("/recovery");
691 if (backup_recovery != NULL) {
692 partition_count++;
693 if (backup_recovery->Backup_Method == 1)
694 file_bytes += backup_recovery->Backup_Size;
695 else
696 img_bytes += backup_recovery->Backup_Size;
697 } else {
698 LOGE("Unable to locate recovery partition.\n");
699 return false;
700 }
701 }
702 DataManager::GetValue(TW_BACKUP_BOOT_VAR, check);
703 if (check) {
704 backup_boot = Find_Partition_By_Path("/boot");
705 if (backup_boot != NULL) {
706 partition_count++;
707 if (backup_boot->Backup_Method == 1)
708 file_bytes += backup_boot->Backup_Size;
709 else
710 img_bytes += backup_boot->Backup_Size;
711 } else {
712 LOGE("Unable to locate boot partition.\n");
713 return false;
714 }
715 }
716 DataManager::GetValue(TW_BACKUP_ANDSEC_VAR, check);
717 if (check) {
718 backup_andsec = Find_Partition_By_Path("/and-sec");
719 if (backup_andsec != NULL) {
720 partition_count++;
721 if (backup_andsec->Backup_Method == 1)
722 file_bytes += backup_andsec->Backup_Size;
723 else
724 img_bytes += backup_andsec->Backup_Size;
725 } else {
726 LOGE("Unable to locate android secure partition.\n");
727 return false;
728 }
729 }
730 DataManager::GetValue(TW_BACKUP_SDEXT_VAR, check);
731 if (check) {
732 backup_sdext = Find_Partition_By_Path("/sd-ext");
733 if (backup_sdext != NULL) {
734 partition_count++;
735 if (backup_sdext->Backup_Method == 1)
736 file_bytes += backup_sdext->Backup_Size;
737 else
738 img_bytes += backup_sdext->Backup_Size;
739 } else {
740 LOGE("Unable to locate sd-ext partition.\n");
741 return false;
742 }
743 }
744#ifdef SP1_NAME
745 DataManager::GetValue(TW_BACKUP_SP1_VAR, check);
746 if (check) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400747 backup_sp1 = Find_Partition_By_Path(EXPAND(SP1_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400748 if (backup_sp1 != NULL) {
749 partition_count++;
750 if (backup_sp1->Backup_Method == 1)
751 file_bytes += backup_sp1->Backup_Size;
752 else
753 img_bytes += backup_sp1->Backup_Size;
754 } else {
Dees_Troyab10ee22012-09-21 14:27:30 -0400755 LOGE("Unable to locate %s partition.\n", EXPAND(SP1_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400756 return false;
757 }
758 }
759#endif
760#ifdef SP2_NAME
761 DataManager::GetValue(TW_BACKUP_SP2_VAR, check);
762 if (check) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400763 backup_sp2 = Find_Partition_By_Path(EXPAND(SP2_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400764 if (backup_sp2 != NULL) {
765 partition_count++;
766 if (backup_sp2->Backup_Method == 1)
767 file_bytes += backup_sp2->Backup_Size;
768 else
769 img_bytes += backup_sp2->Backup_Size;
770 } else {
Dees_Troyab10ee22012-09-21 14:27:30 -0400771 LOGE("Unable to locate %s partition.\n", EXPAND(SP2_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400772 return false;
773 }
774 }
775#endif
776#ifdef SP3_NAME
777 DataManager::GetValue(TW_BACKUP_SP3_VAR, check);
778 if (check) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400779 backup_sp3 = Find_Partition_By_Path(EXPAND(SP3_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400780 if (backup_sp3 != NULL) {
781 partition_count++;
782 if (backup_sp3->Backup_Method == 1)
783 file_bytes += backup_sp3->Backup_Size;
784 else
785 img_bytes += backup_sp3->Backup_Size;
786 } else {
Dees_Troyab10ee22012-09-21 14:27:30 -0400787 LOGE("Unable to locate %s partition.\n", EXPAND(SP3_NAME));
Dees_Troy43d8b002012-09-17 16:00:01 -0400788 return false;
789 }
790 }
791#endif
792
793 if (partition_count == 0) {
794 ui_print("No partitions selected for backup.\n");
795 return false;
796 }
797 total_bytes = file_bytes + img_bytes;
798 ui_print(" * Total number of partitions to back up: %d\n", partition_count);
799 ui_print(" * Total size of all data: %lluMB\n", total_bytes / 1024 / 1024);
800 storage = Find_Partition_By_Path(DataManager::GetCurrentStoragePath());
801 if (storage != NULL) {
802 free_space = storage->Free;
803 ui_print(" * Available space: %lluMB\n", free_space / 1024 / 1024);
804 } else {
805 LOGE("Unable to locate storage device.\n");
806 return false;
807 }
808 if (free_space + (32 * 1024 * 1024) < total_bytes) {
809 // We require an extra 32MB just in case
810 LOGE("Not enough free space on storage.\n");
811 return false;
812 }
813 img_bytes_remaining = img_bytes;
814 file_bytes_remaining = file_bytes;
815
Dees_Troy093b7642012-09-21 15:59:38 -0400816 ui->SetProgress(0.0);
817
818 if (!Backup_Partition(backup_sys, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400819 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400820 if (!Backup_Partition(backup_data, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400821 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400822 if (!Backup_Partition(backup_cache, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400823 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400824 if (!Backup_Partition(backup_recovery, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400825 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400826 if (!Backup_Partition(backup_boot, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400827 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400828 if (!Backup_Partition(backup_andsec, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400829 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400830 if (!Backup_Partition(backup_sdext, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400831 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400832 if (!Backup_Partition(backup_sp1, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400833 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400834 if (!Backup_Partition(backup_sp2, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400835 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400836 if (!Backup_Partition(backup_sp3, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
Dees_Troy43d8b002012-09-17 16:00:01 -0400837 return false;
838
839 // Average BPS
840 if (img_time == 0)
841 img_time = 1;
842 if (file_time == 0)
843 file_time = 1;
Dees_Troy093b7642012-09-21 15:59:38 -0400844 int img_bps = (int)img_bytes / (int)img_time;
845 int file_bps = (int)file_bytes / (int)file_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400846
847 ui_print("Average backup rate for file systems: %lu MB/sec\n", (file_bps / (1024 * 1024)));
848 ui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));
849
850 time(&total_stop);
851 int total_time = (int) difftime(total_stop, total_start);
852 unsigned long long actual_backup_size = TWFunc::Get_Folder_Size(Full_Backup_Path, true);
853 actual_backup_size /= (1024LLU * 1024LLU);
854
Dees_Troy093b7642012-09-21 15:59:38 -0400855 int prev_img_bps, prev_file_bps, use_compression;
856 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, prev_img_bps);
857 img_bps += (prev_img_bps * 4);
858 img_bps /= 5;
859
860 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
861 if (use_compression)
862 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, prev_file_bps);
863 else
864 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, prev_file_bps);
865 file_bps += (prev_file_bps * 4);
866 file_bps /= 5;
867
868 DataManager::SetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
869 if (use_compression)
870 DataManager::SetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
871 else
872 DataManager::SetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
873
Dees_Troy43d8b002012-09-17 16:00:01 -0400874 ui_print("[%llu MB TOTAL BACKED UP]\n", actual_backup_size);
875 Update_System_Details();
876 ui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
877 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400878}
879
Dees_Troy093b7642012-09-21 15:59:38 -0400880bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Name, int partition_count) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400881 time_t Start, Stop;
882 time(&Start);
Dees_Troy093b7642012-09-21 15:59:38 -0400883 ui->ShowProgress(1.0 / (float)partition_count, 150);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400884 if (!Part->Restore(Restore_Name))
885 return false;
Dees_Troy8170a922012-09-18 15:40:25 -0400886 if (Part->Has_SubPartition) {
887 std::vector<TWPartition*>::iterator subpart;
888
889 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
890 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
891 if (!(*subpart)->Restore(Restore_Name))
892 return false;
893 }
894 }
895 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400896 time(&Stop);
897 ui_print("[%s done (%d seconds)]\n\n", Part->Display_Name.c_str(), (int)difftime(Stop, Start));
898 return true;
899}
900
Dees_Troy51a0e822012-09-05 15:24:24 -0400901int TWPartitionManager::Run_Restore(string Restore_Name) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400902 int check_md5, check, partition_count = 0;
903 TWPartition* restore_sys = NULL;
904 TWPartition* restore_data = NULL;
905 TWPartition* restore_cache = NULL;
906 TWPartition* restore_boot = NULL;
907 TWPartition* restore_andsec = NULL;
908 TWPartition* restore_sdext = NULL;
909 TWPartition* restore_sp1 = NULL;
910 TWPartition* restore_sp2 = NULL;
911 TWPartition* restore_sp3 = NULL;
912 time_t rStart, rStop;
913 time(&rStart);
Dees_Troy43d8b002012-09-17 16:00:01 -0400914
Dees_Troy4a2a1262012-09-18 09:33:47 -0400915 ui_print("\n[RESTORE STARTED]\n\n");
916 ui_print("Restore folder: '%s'\n", Restore_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400917
Dees_Troy4a2a1262012-09-18 09:33:47 -0400918 if (!Mount_Current_Storage(true))
919 return false;
920
921 DataManager::GetValue(TW_SKIP_MD5_CHECK_VAR, check_md5);
922 DataManager::GetValue(TW_RESTORE_SYSTEM_VAR, check);
Dees_Troy63c8df72012-09-10 14:02:05 -0400923 if (check > 0) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400924 restore_sys = Find_Partition_By_Path("/system");
925 if (restore_sys == NULL) {
926 LOGE("Unable to locate system partition.\n");
927 return false;
928 }
929 partition_count++;
930 }
931 DataManager::GetValue(TW_RESTORE_DATA_VAR, check);
932 if (check > 0) {
933 restore_data = Find_Partition_By_Path("/data");
934 if (restore_data == NULL) {
935 LOGE("Unable to locate data partition.\n");
936 return false;
937 }
938 partition_count++;
939 }
940 DataManager::GetValue(TW_RESTORE_CACHE_VAR, check);
941 if (check > 0) {
942 restore_cache = Find_Partition_By_Path("/cache");
943 if (restore_cache == NULL) {
944 LOGE("Unable to locate cache partition.\n");
945 return false;
946 }
947 partition_count++;
948 }
949 DataManager::GetValue(TW_RESTORE_BOOT_VAR, check);
950 if (check > 0) {
951 restore_boot = Find_Partition_By_Path("/boot");
952 if (restore_boot == NULL) {
953 LOGE("Unable to locate boot partition.\n");
954 return false;
955 }
956 partition_count++;
957 }
958 DataManager::GetValue(TW_RESTORE_ANDSEC_VAR, check);
959 if (check > 0) {
960 restore_andsec = Find_Partition_By_Path("/and-sec");
961 if (restore_andsec == NULL) {
962 LOGE("Unable to locate android secure partition.\n");
963 return false;
964 }
965 partition_count++;
966 }
967 DataManager::GetValue(TW_RESTORE_SDEXT_VAR, check);
968 if (check > 0) {
969 restore_sdext = Find_Partition_By_Path("/sd-ext");
970 if (restore_sdext == NULL) {
971 LOGE("Unable to locate sd-ext partition.\n");
972 return false;
973 }
974 partition_count++;
975 }
976#ifdef SP1_NAME
977 DataManager::GetValue(TW_RESTORE_SP1_VAR, check);
978 if (check > 0) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400979 restore_sp1 = Find_Partition_By_Path(EXPAND(SP1_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400980 if (restore_sp1 == NULL) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400981 LOGE("Unable to locate %s partition.\n", EXPAND(SP1_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400982 return false;
983 }
984 partition_count++;
985 }
986#endif
987#ifdef SP2_NAME
988 DataManager::GetValue(TW_RESTORE_SP2_VAR, check);
989 if (check > 0) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400990 restore_sp2 = Find_Partition_By_Path(EXPAND(SP2_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400991 if (restore_sp2 == NULL) {
Dees_Troyab10ee22012-09-21 14:27:30 -0400992 LOGE("Unable to locate %s partition.\n", EXPAND(SP2_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400993 return false;
994 }
995 partition_count++;
996 }
997#endif
998#ifdef SP3_NAME
999 DataManager::GetValue(TW_RESTORE_SP3_VAR, check);
1000 if (check > 0) {
Dees_Troyab10ee22012-09-21 14:27:30 -04001001 restore_sp3 = Find_Partition_By_Path(EXPAND(SP3_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -04001002 if (restore_sp3 == NULL) {
Dees_Troyab10ee22012-09-21 14:27:30 -04001003 LOGE("Unable to locate %s partition.\n", EXPAND(SP3_NAME));
Dees_Troy4a2a1262012-09-18 09:33:47 -04001004 return false;
1005 }
1006 partition_count++;
1007 }
1008#endif
1009
1010 if (partition_count == 0) {
1011 LOGE("No partitions selected for restore.\n");
1012 return false;
1013 }
1014
1015 if (check_md5 > 0) {
Dees_Troy43d8b002012-09-17 16:00:01 -04001016 // Check MD5 files first before restoring to ensure that all of them match before starting a restore
Dees_Troyb46a6842012-09-25 11:06:46 -04001017 TWFunc::GUI_Operation_Text(TW_VERIFY_MD5_TEXT, "Verifying MD5");
Dees_Troy4a2a1262012-09-18 09:33:47 -04001018 ui_print("Verifying MD5...\n");
1019 if (restore_sys != NULL && !restore_sys->Check_MD5(Restore_Name))
1020 return false;
1021 if (restore_data != NULL && !restore_data->Check_MD5(Restore_Name))
1022 return false;
Dees_Troy8170a922012-09-18 15:40:25 -04001023 if (restore_data != NULL && restore_data->Has_SubPartition) {
1024 std::vector<TWPartition*>::iterator subpart;
1025
1026 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1027 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == restore_data->Mount_Point) {
1028 if (!(*subpart)->Check_MD5(Restore_Name))
1029 return false;
1030 }
1031 }
1032 }
Dees_Troy4a2a1262012-09-18 09:33:47 -04001033 if (restore_cache != NULL && !restore_cache->Check_MD5(Restore_Name))
1034 return false;
1035 if (restore_boot != NULL && !restore_boot->Check_MD5(Restore_Name))
1036 return false;
1037 if (restore_andsec != NULL && !restore_andsec->Check_MD5(Restore_Name))
1038 return false;
1039 if (restore_sdext != NULL && !restore_sdext->Check_MD5(Restore_Name))
1040 return false;
1041 if (restore_sp1 != NULL && !restore_sp1->Check_MD5(Restore_Name))
1042 return false;
1043 if (restore_sp2 != NULL && !restore_sp2->Check_MD5(Restore_Name))
1044 return false;
1045 if (restore_sp3 != NULL && !restore_sp3->Check_MD5(Restore_Name))
1046 return false;
1047 ui_print("Done verifying MD5.\n");
1048 } else
1049 ui_print("Skipping MD5 check based on user setting.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -04001050
Dees_Troy4a2a1262012-09-18 09:33:47 -04001051 ui_print("Restoring %i partitions...\n", partition_count);
Dees_Troy093b7642012-09-21 15:59:38 -04001052 ui->SetProgress(0.0);
1053 if (restore_sys != NULL && !Restore_Partition(restore_sys, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001054 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001055 if (restore_data != NULL && !Restore_Partition(restore_data, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001056 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001057 if (restore_cache != NULL && !Restore_Partition(restore_cache, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001058 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001059 if (restore_boot != NULL && !Restore_Partition(restore_boot, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001060 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001061 if (restore_andsec != NULL && !Restore_Partition(restore_andsec, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001062 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001063 if (restore_sdext != NULL && !Restore_Partition(restore_sdext, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001064 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001065 if (restore_sp1 != NULL && !Restore_Partition(restore_sp1, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001066 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001067 if (restore_sp2 != NULL && !Restore_Partition(restore_sp2, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001068 return false;
Dees_Troy093b7642012-09-21 15:59:38 -04001069 if (restore_sp3 != NULL && !Restore_Partition(restore_sp3, Restore_Name, partition_count))
Dees_Troy4a2a1262012-09-18 09:33:47 -04001070 return false;
Dees_Troy43d8b002012-09-17 16:00:01 -04001071
Dees_Troyb46a6842012-09-25 11:06:46 -04001072 TWFunc::GUI_Operation_Text(TW_UPDATE_SYSTEM_DETAILS_TEXT, "Updating System Details");
Dees_Troy43d8b002012-09-17 16:00:01 -04001073 Update_System_Details();
Dees_Troy4a2a1262012-09-18 09:33:47 -04001074 time(&rStop);
1075 ui_print("[RESTORE COMPLETED IN %d SECONDS]\n\n",(int)difftime(rStop,rStart));
Dees_Troy63c8df72012-09-10 14:02:05 -04001076 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -04001077}
1078
1079void TWPartitionManager::Set_Restore_Files(string Restore_Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001080 // Start with the default values
1081 int tw_restore_system = -1;
1082 int tw_restore_data = -1;
1083 int tw_restore_cache = -1;
1084 int tw_restore_recovery = -1;
1085 int tw_restore_boot = -1;
1086 int tw_restore_andsec = -1;
1087 int tw_restore_sdext = -1;
1088 int tw_restore_sp1 = -1;
1089 int tw_restore_sp2 = -1;
1090 int tw_restore_sp3 = -1;
1091 bool get_date = true;
1092
1093 DIR* d;
1094 d = opendir(Restore_Name.c_str());
1095 if (d == NULL)
1096 {
1097 LOGE("Error opening %s\n", Restore_Name.c_str());
1098 return;
1099 }
1100
1101 struct dirent* de;
1102 while ((de = readdir(d)) != NULL)
1103 {
1104 // Strip off three components
1105 char str[256];
1106 char* label;
1107 char* fstype = NULL;
1108 char* extn = NULL;
1109 char* ptr;
1110
1111 strcpy(str, de->d_name);
1112 if (strlen(str) <= 2)
1113 continue;
1114
1115 if (get_date) {
1116 char file_path[255];
1117 struct stat st;
1118
1119 strcpy(file_path, Restore_Name.c_str());
1120 strcat(file_path, "/");
1121 strcat(file_path, str);
1122 stat(file_path, &st);
1123 string backup_date = ctime((const time_t*)(&st.st_mtime));
1124 DataManager::SetValue(TW_RESTORE_FILE_DATE, backup_date);
1125 get_date = false;
1126 }
1127
1128 label = str;
1129 ptr = label;
1130 while (*ptr && *ptr != '.') ptr++;
1131 if (*ptr == '.')
1132 {
1133 *ptr = 0x00;
1134 ptr++;
1135 fstype = ptr;
1136 }
1137 while (*ptr && *ptr != '.') ptr++;
1138 if (*ptr == '.')
1139 {
1140 *ptr = 0x00;
1141 ptr++;
1142 extn = ptr;
1143 }
1144
1145 if (extn == NULL || (strlen(extn) >= 3 && strncmp(extn, "win", 3) != 0)) continue;
1146
1147 TWPartition* Part = Find_Partition_By_Path(label);
1148 if (Part == NULL)
1149 {
1150 LOGE(" Unable to locate partition by backup name: '%s'\n", label);
1151 continue;
1152 }
1153
1154 Part->Backup_FileName = de->d_name;
1155 if (strlen(extn) > 3) {
1156 Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3);
1157 }
1158
1159 // Now, we just need to find the correct label
Dees_Troye58d5262012-09-21 12:27:57 -04001160 if (Part->Backup_Path == "/system")
Dees_Troy63c8df72012-09-10 14:02:05 -04001161 tw_restore_system = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001162 if (Part->Backup_Path == "/data")
Dees_Troy63c8df72012-09-10 14:02:05 -04001163 tw_restore_data = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001164 if (Part->Backup_Path == "/cache")
Dees_Troy63c8df72012-09-10 14:02:05 -04001165 tw_restore_cache = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001166 if (Part->Backup_Path == "/recovery")
Dees_Troy63c8df72012-09-10 14:02:05 -04001167 tw_restore_recovery = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001168 if (Part->Backup_Path == "/boot")
Dees_Troy63c8df72012-09-10 14:02:05 -04001169 tw_restore_boot = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001170 if (Part->Backup_Path == "/and-sec")
Dees_Troy63c8df72012-09-10 14:02:05 -04001171 tw_restore_andsec = 1;
Dees_Troye58d5262012-09-21 12:27:57 -04001172 if (Part->Backup_Path == "/sd-ext")
Dees_Troy63c8df72012-09-10 14:02:05 -04001173 tw_restore_sdext = 1;
1174#ifdef SP1_NAME
Dees_Troyab10ee22012-09-21 14:27:30 -04001175 if (Part->Backup_Path == TWFunc::Get_Root_Path(EXPAND(SP1_NAME)))
Dees_Troy63c8df72012-09-10 14:02:05 -04001176 tw_restore_sp1 = 1;
1177#endif
1178#ifdef SP2_NAME
Dees_Troyab10ee22012-09-21 14:27:30 -04001179 if (Part->Backup_Path == TWFunc::Get_Root_Path(EXPAND(SP2_NAME)))
Dees_Troy63c8df72012-09-10 14:02:05 -04001180 tw_restore_sp2 = 1;
1181#endif
1182#ifdef SP3_NAME
Dees_Troyab10ee22012-09-21 14:27:30 -04001183 if (Part->Backup_Path == TWFunc::Get_Root_Path(EXPAND(SP3_NAME)))
Dees_Troy63c8df72012-09-10 14:02:05 -04001184 tw_restore_sp3 = 1;
1185#endif
1186 }
1187 closedir(d);
1188
1189 // Set the final values
1190 DataManager::SetValue(TW_RESTORE_SYSTEM_VAR, tw_restore_system);
1191 DataManager::SetValue(TW_RESTORE_DATA_VAR, tw_restore_data);
1192 DataManager::SetValue(TW_RESTORE_CACHE_VAR, tw_restore_cache);
1193 DataManager::SetValue(TW_RESTORE_RECOVERY_VAR, tw_restore_recovery);
1194 DataManager::SetValue(TW_RESTORE_BOOT_VAR, tw_restore_boot);
1195 DataManager::SetValue(TW_RESTORE_ANDSEC_VAR, tw_restore_andsec);
1196 DataManager::SetValue(TW_RESTORE_SDEXT_VAR, tw_restore_sdext);
1197 DataManager::SetValue(TW_RESTORE_SP1_VAR, tw_restore_sp1);
1198 DataManager::SetValue(TW_RESTORE_SP2_VAR, tw_restore_sp2);
1199 DataManager::SetValue(TW_RESTORE_SP3_VAR, tw_restore_sp3);
1200
Dees_Troy51a0e822012-09-05 15:24:24 -04001201 return;
1202}
1203
1204int TWPartitionManager::Wipe_By_Path(string Path) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001205 std::vector<TWPartition*>::iterator iter;
1206 int ret = false;
1207 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04001208 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy63c8df72012-09-10 14:02:05 -04001209
1210 // Iterate through all partitions
1211 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -04001212 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troye58d5262012-09-21 12:27:57 -04001213 if (Path == "/and-sec")
1214 ret = (*iter)->Wipe_AndSec();
1215 else
1216 ret = (*iter)->Wipe();
Dees_Troy63c8df72012-09-10 14:02:05 -04001217 found = true;
1218 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
1219 (*iter)->Wipe();
1220 }
1221 }
1222 if (found) {
1223 return ret;
1224 } else
1225 LOGE("Wipe: Unable to find partition for path '%s'\n", Local_Path.c_str());
1226 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001227}
1228
1229int TWPartitionManager::Wipe_By_Block(string Block) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001230 TWPartition* Part = Find_Partition_By_Block(Block);
1231
1232 if (Part) {
1233 if (Part->Has_SubPartition) {
1234 std::vector<TWPartition*>::iterator subpart;
1235
1236 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1237 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1238 (*subpart)->Wipe();
1239 }
1240 return Part->Wipe();
1241 } else
1242 return Part->Wipe();
1243 }
1244 LOGE("Wipe: Unable to find partition for block '%s'\n", Block.c_str());
1245 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001246}
1247
1248int TWPartitionManager::Wipe_By_Name(string Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001249 TWPartition* Part = Find_Partition_By_Name(Name);
1250
1251 if (Part) {
1252 if (Part->Has_SubPartition) {
1253 std::vector<TWPartition*>::iterator subpart;
1254
1255 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1256 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1257 (*subpart)->Wipe();
1258 }
1259 return Part->Wipe();
1260 } else
1261 return Part->Wipe();
1262 }
1263 LOGE("Wipe: Unable to find partition for name '%s'\n", Name.c_str());
1264 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001265}
1266
1267int TWPartitionManager::Factory_Reset(void) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001268 std::vector<TWPartition*>::iterator iter;
1269 int ret = true;
1270
1271 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001272 if ((*iter)->Wipe_During_Factory_Reset && (*iter)->Is_Present) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001273 if (!(*iter)->Wipe())
1274 ret = false;
Dees_Troy094207a2012-09-26 12:00:39 -04001275 } else if ((*iter)->Has_Android_Secure) {
1276 if (!(*iter)->Wipe_AndSec())
1277 ret = false;
Dees_Troy63c8df72012-09-10 14:02:05 -04001278 }
1279 }
1280 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001281}
1282
Dees_Troy38bd7602012-09-14 13:33:53 -04001283int TWPartitionManager::Wipe_Dalvik_Cache(void) {
1284 struct stat st;
1285
1286 if (!Mount_By_Path("/data", true))
1287 return false;
1288
1289 if (!Mount_By_Path("/cache", true))
1290 return false;
1291
1292 ui_print("\nWiping Dalvik Cache Directories...\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001293 system("rm -rf /data/dalvik-cache");
Dees_Troy38bd7602012-09-14 13:33:53 -04001294 ui_print("Cleaned: /data/dalvik-cache...\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001295 system("rm -rf /cache/dalvik-cache");
Dees_Troy38bd7602012-09-14 13:33:53 -04001296 ui_print("Cleaned: /cache/dalvik-cache...\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001297 system("rm -rf /cache/dc");
Dees_Troy38bd7602012-09-14 13:33:53 -04001298 ui_print("Cleaned: /cache/dc\n");
1299
1300 TWPartition* sdext = Find_Partition_By_Path("/sd-ext");
1301 if (sdext != NULL) {
1302 if (sdext->Is_Present && sdext->Mount(false)) {
1303 if (stat("/sd-ext/dalvik-cache", &st) == 0) {
Dees_Troy8170a922012-09-18 15:40:25 -04001304 system("rm -rf /sd-ext/dalvik-cache");
Dees_Troy38bd7602012-09-14 13:33:53 -04001305 ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
1306 }
1307 }
1308 }
1309 ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
1310 return true;
1311}
1312
1313int TWPartitionManager::Wipe_Rotate_Data(void) {
1314 if (!Mount_By_Path("/data", true))
1315 return false;
1316
Dees_Troy8170a922012-09-18 15:40:25 -04001317 system("rm -r /data/misc/akmd*");
1318 system("rm -r /data/misc/rild*");
1319 system("rm -r /data/misc/rild*");
Dees_Troy38bd7602012-09-14 13:33:53 -04001320 ui_print("Rotation data wiped.\n");
1321 return true;
1322}
1323
1324int TWPartitionManager::Wipe_Battery_Stats(void) {
1325 struct stat st;
1326
1327 if (!Mount_By_Path("/data", true))
1328 return false;
1329
1330 if (0 != stat("/data/system/batterystats.bin", &st)) {
1331 ui_print("No Battery Stats Found. No Need To Wipe.\n");
1332 } else {
1333 remove("/data/system/batterystats.bin");
1334 ui_print("Cleared battery stats.\n");
1335 }
1336 return true;
1337}
1338
Dees_Troy2ff5a8d2012-09-26 14:53:02 -04001339int TWPartitionManager::Wipe_Android_Secure(void) {
1340 std::vector<TWPartition*>::iterator iter;
1341 int ret = false;
1342 bool found = false;
1343
1344 // Iterate through all partitions
1345 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1346 if ((*iter)->Has_Android_Secure) {
1347 ret = (*iter)->Wipe_AndSec();
1348 found = true;
1349 }
1350 }
1351 if (found) {
1352 return ret;
1353 } else {
1354 LOGE("No android secure partitions found.\n");
1355 }
1356 return false;
1357}
1358
Dees_Troy38bd7602012-09-14 13:33:53 -04001359int TWPartitionManager::Format_Data(void) {
1360 TWPartition* dat = Find_Partition_By_Path("/data");
1361
1362 if (dat != NULL) {
1363 if (!dat->UnMount(true))
1364 return false;
1365
1366 return dat->Wipe_Encryption();
1367 } else {
1368 LOGE("Unable to locate /data.\n");
1369 return false;
1370 }
1371 return false;
1372}
1373
1374int TWPartitionManager::Wipe_Media_From_Data(void) {
1375 TWPartition* dat = Find_Partition_By_Path("/data");
1376
1377 if (dat != NULL) {
1378 if (!dat->Has_Data_Media) {
1379 LOGE("This device does not have /data/media\n");
1380 return false;
1381 }
1382 if (!dat->Mount(true))
1383 return false;
1384
1385 ui_print("Wiping internal storage -- /data/media...\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001386 system("rm -rf /data/media");
1387 system("cd /data && mkdir media && chmod 775 media");
Dees_Troy38bd7602012-09-14 13:33:53 -04001388 if (dat->Has_Data_Media) {
1389 dat->Recreate_Media_Folder();
1390 }
1391 return true;
1392 } else {
1393 LOGE("Unable to locate /data.\n");
1394 return false;
1395 }
1396 return false;
1397}
1398
Dees_Troy51a0e822012-09-05 15:24:24 -04001399void TWPartitionManager::Refresh_Sizes(void) {
Dees_Troy51127312012-09-08 13:08:49 -04001400 Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -04001401 return;
1402}
1403
1404void TWPartitionManager::Update_System_Details(void) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001405 std::vector<TWPartition*>::iterator iter;
Dees_Troy51127312012-09-08 13:08:49 -04001406 int data_size = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -04001407
Dees_Troy32c8eb82012-09-11 15:28:06 -04001408 ui_print("Updating partition details...\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001409 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -04001410 if ((*iter)->Can_Be_Mounted) {
1411 (*iter)->Update_Size(true);
1412 if ((*iter)->Mount_Point == "/system") {
1413 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1414 DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size);
1415 } else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") {
1416 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
1417 } else if ((*iter)->Mount_Point == "/cache") {
1418 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1419 DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size);
1420 } else if ((*iter)->Mount_Point == "/sd-ext") {
1421 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1422 DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size);
1423 if ((*iter)->Backup_Size == 0) {
1424 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0);
1425 DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0);
1426 } else
1427 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1);
Dees_Troye58d5262012-09-21 12:27:57 -04001428 } else if ((*iter)->Has_Android_Secure) {
Dees_Troy8170a922012-09-18 15:40:25 -04001429 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
Dees_Troye58d5262012-09-21 12:27:57 -04001430 DataManager::SetValue(TW_BACKUP_ANDSEC_SIZE, backup_display_size);
Dees_Troy8170a922012-09-18 15:40:25 -04001431 if ((*iter)->Backup_Size == 0) {
1432 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 0);
1433 DataManager::SetValue(TW_BACKUP_ANDSEC_VAR, 0);
1434 } else
1435 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 1);
Dees_Troy2c50e182012-09-26 20:05:28 -04001436 } else if ((*iter)->Mount_Point == "/boot") {
1437 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1438 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
1439 if ((*iter)->Backup_Size == 0) {
1440 DataManager::SetValue("tw_has_boot_partition", 0);
1441 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
1442 } else
1443 DataManager::SetValue("tw_has_boot_partition", 1);
Dees_Troy51127312012-09-08 13:08:49 -04001444 }
Dees_Troyab10ee22012-09-21 14:27:30 -04001445#ifdef SP1_NAME
1446 if ((*iter)->Backup_Name == EXPAND(SP1_NAME)) {
1447 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1448 DataManager::SetValue(TW_BACKUP_SP1_SIZE, backup_display_size);
1449 }
1450#endif
1451#ifdef SP2_NAME
1452 if ((*iter)->Backup_Name == EXPAND(SP2_NAME)) {
1453 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1454 DataManager::SetValue(TW_BACKUP_SP2_SIZE, backup_display_size);
1455 }
1456#endif
1457#ifdef SP3_NAME
1458 if ((*iter)->Backup_Name == EXPAND(SP3_NAME)) {
1459 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1460 DataManager::SetValue(TW_BACKUP_SP3_SIZE, backup_display_size);
1461 }
1462#endif
Dees_Troy51127312012-09-08 13:08:49 -04001463 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001464 }
Dees_Troy51127312012-09-08 13:08:49 -04001465 DataManager::SetValue(TW_BACKUP_DATA_SIZE, data_size);
1466 string current_storage_path = DataManager::GetCurrentStoragePath();
1467 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
Dees_Troy8170a922012-09-18 15:40:25 -04001468 if (FreeStorage != NULL) {
1469 // Attempt to mount storage
1470 if (!FreeStorage->Mount(false)) {
1471 // We couldn't mount storage... check to see if we have dual storage
1472 int has_dual_storage;
1473 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual_storage);
1474 if (has_dual_storage == 1) {
1475 // We have dual storage, see if we're using the internal storage that should always be present
1476 if (current_storage_path == DataManager::GetSettingsStoragePath()) {
Dees_Troyab10ee22012-09-21 14:27:30 -04001477 if (!FreeStorage->Is_Encrypted) {
1478 // Not able to use internal, so error!
1479 LOGE("Unable to mount internal storage.\n");
1480 }
Dees_Troy8170a922012-09-18 15:40:25 -04001481 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1482 } else {
1483 // We were using external, flip to internal
1484 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0);
1485 current_storage_path = DataManager::GetCurrentStoragePath();
1486 FreeStorage = Find_Partition_By_Path(current_storage_path);
1487 if (FreeStorage != NULL) {
1488 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1489 } else {
1490 LOGE("Unable to locate internal storage partition.\n");
1491 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1492 }
1493 }
1494 } else {
1495 // No dual storage and unable to mount storage, error!
1496 LOGE("Unable to mount storage.\n");
1497 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1498 }
1499 } else {
1500 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1501 }
1502 } else {
Dees_Troy51127312012-09-08 13:08:49 -04001503 LOGI("Unable to find storage partition '%s'.\n", current_storage_path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -04001504 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001505 if (!Write_Fstab())
1506 LOGE("Error creating fstab\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001507 return;
1508}
1509
1510int TWPartitionManager::Decrypt_Device(string Password) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001511#ifdef TW_INCLUDE_CRYPTO
1512 int ret_val, password_len;
1513 char crypto_blkdev[255], cPassword[255];
1514 size_t result;
1515
1516 property_set("ro.crypto.state", "encrypted");
1517#ifdef TW_INCLUDE_JB_CRYPTO
1518 // No extra flags needed
1519#else
1520 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
1521 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
1522 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
1523 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
1524 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
1525 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
1526#endif
1527 strcpy(cPassword, Password.c_str());
1528 if (cryptfs_check_passwd(cPassword) != 0) {
1529 LOGE("Failed to decrypt data.\n");
1530 return -1;
1531 }
1532 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
1533 if (strcmp(crypto_blkdev, "error") == 0) {
1534 LOGE("Error retrieving decrypted data block device.\n");
1535 } else {
1536 TWPartition* dat = Find_Partition_By_Path("/data");
1537 if (dat != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001538 DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Primary_Block_Device);
Dees_Troy5bf43922012-09-07 16:07:55 -04001539 DataManager::SetValue(TW_IS_DECRYPTED, 1);
1540 dat->Is_Decrypted = true;
1541 dat->Decrypted_Block_Device = crypto_blkdev;
Dees_Troy32c8eb82012-09-11 15:28:06 -04001542 ui_print("Data successfully decrypted, new block device: '%s'\n", crypto_blkdev);
Dees_Troy5bf43922012-09-07 16:07:55 -04001543 // Sleep for a bit so that the device will be ready
1544 sleep(1);
1545 Update_System_Details();
1546 } else
1547 LOGE("Unable to locate data partition.\n");
1548 }
1549 return 0;
1550#else
1551 LOGE("No crypto support was compiled into this build.\n");
1552 return -1;
1553#endif
Dees_Troy51a0e822012-09-05 15:24:24 -04001554 return 1;
Dees_Troy51127312012-09-08 13:08:49 -04001555}
1556
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001557int TWPartitionManager::Fix_Permissions(void) {
1558 int result = 0;
1559 if (!Mount_By_Path("/data", true))
1560 return false;
1561
1562 if (!Mount_By_Path("/system", true))
1563 return false;
1564
1565 Mount_By_Path("/sd-ext", false);
1566
1567 fixPermissions perms;
1568 result = perms.fixPerms(true, false);
1569 ui_print("Done.\n\n");
1570 return result;
1571}
1572
Dees_Troy8170a922012-09-18 15:40:25 -04001573//partial kangbang from system/vold
1574#ifndef CUSTOM_LUN_FILE
1575#define CUSTOM_LUN_FILE "/sys/devices/platform/usb_mass_storage/lun%d/file"
1576#endif
1577
1578int TWPartitionManager::usb_storage_enable(void) {
1579 int fd, has_dual, has_data_media;
1580 char lun_file[255];
1581 TWPartition* Part;
1582 string ext_path;
1583
1584 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual);
1585 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
1586 if (has_dual == 1 && has_data_media == 0) {
1587 Part = Find_Partition_By_Path(DataManager::GetSettingsStoragePath());
1588 if (Part == NULL) {
1589 LOGE("Unable to locate volume information.");
1590 return false;
1591 }
1592 if (!Part->UnMount(true))
1593 return false;
1594
1595 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
1596 if ((fd = open(lun_file, O_WRONLY)) < 0) {
1597 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1598 return false;
1599 }
1600
1601 if (write(fd, Part->Actual_Block_Device.c_str(), Part->Actual_Block_Device.size()) < 0) {
1602 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1603 close(fd);
1604 return false;
1605 }
1606 close(fd);
1607
1608 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
1609 Part = Find_Partition_By_Path(ext_path);
1610 if (Part == NULL) {
1611 LOGE("Unable to locate volume information.\n");
1612 return false;
1613 }
1614 if (!Part->UnMount(true))
1615 return false;
1616
1617 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
1618 if ((fd = open(lun_file, O_WRONLY)) < 0) {
1619 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1620 return false;
1621 }
1622
1623 if (write(fd, Part->Actual_Block_Device.c_str(), Part->Actual_Block_Device.size()) < 0) {
1624 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1625 close(fd);
1626 return false;
1627 }
1628 close(fd);
1629 } else {
1630 if (has_data_media == 0)
1631 ext_path = DataManager::GetCurrentStoragePath();
1632 else
1633 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
1634
1635 Part = Find_Partition_By_Path(ext_path);
1636 if (Part == NULL) {
1637 LOGE("Unable to locate volume information.\n");
1638 return false;
1639 }
1640 if (!Part->UnMount(true))
1641 return false;
1642
1643 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
1644
1645 if ((fd = open(lun_file, O_WRONLY)) < 0) {
1646 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1647 return false;
1648 }
1649
1650 if (write(fd, Part->Actual_Block_Device.c_str(), Part->Actual_Block_Device.size()) < 0) {
1651 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
1652 close(fd);
1653 return false;
1654 }
1655 close(fd);
1656 }
1657 return true;
1658}
1659
1660int TWPartitionManager::usb_storage_disable(void) {
1661 int fd, index;
1662 char lun_file[255];
1663
1664 for (index=0; index<2; index++) {
1665 sprintf(lun_file, CUSTOM_LUN_FILE, index);
1666
1667 if ((fd = open(lun_file, O_WRONLY)) < 0) {
Dees_Troye58d5262012-09-21 12:27:57 -04001668 Mount_All_Storage();
1669 Update_System_Details();
1670 if (index == 0) {
Dees_Troy8170a922012-09-18 15:40:25 -04001671 LOGE("Unable to open ums lunfile '%s': (%s)", lun_file, strerror(errno));
Dees_Troye58d5262012-09-21 12:27:57 -04001672 return false;
1673 } else
1674 return true;
Dees_Troy8170a922012-09-18 15:40:25 -04001675 }
1676
1677 char ch = 0;
1678 if (write(fd, &ch, 1) < 0) {
Dees_Troy8170a922012-09-18 15:40:25 -04001679 close(fd);
Dees_Troye58d5262012-09-21 12:27:57 -04001680 Mount_All_Storage();
1681 Update_System_Details();
1682 if (index == 0) {
1683 LOGE("Unable to write to ums lunfile '%s': (%s)", lun_file, strerror(errno));
1684 return false;
1685 } else
1686 return true;
Dees_Troy8170a922012-09-18 15:40:25 -04001687 }
1688
1689 close(fd);
1690 }
Dees_Troye58d5262012-09-21 12:27:57 -04001691 Mount_All_Storage();
1692 Update_System_Details();
Dees_Troy8170a922012-09-18 15:40:25 -04001693 return true;
Dees_Troy812660f2012-09-20 09:55:17 -04001694}
1695
1696void TWPartitionManager::Mount_All_Storage(void) {
1697 std::vector<TWPartition*>::iterator iter;
1698
1699 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1700 if ((*iter)->Is_Storage)
1701 (*iter)->Mount(false);
1702 }
Dees_Troy2c50e182012-09-26 20:05:28 -04001703}
Dees_Troy9350b8d2012-09-27 12:38:38 -04001704
1705int TWPartitionManager::Partition_SDCard(void) {
1706 char mkdir_path[255], temp[255], line[512];
1707 string Command, Device, fat_str, ext_str, swap_str, start_loc, end_loc, ext_format, sd_path, tmpdevice;
1708 int ext, swap, total_size = 0, fat_size;
1709 FILE* fp;
1710
1711 ui_print("Partitioning SD Card...\n");
1712#ifdef TW_EXTERNAL_STORAGE_PATH
1713 TWPartition* SDCard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH));
1714#else
1715 TWPartition* SDCard = Find_Partition_By_Path("/sdcard");
1716#endif
1717 if (SDCard == NULL) {
1718 LOGE("Unable to locate device to partition.\n");
1719 return false;
1720 }
1721 if (!SDCard->UnMount(true))
1722 return false;
1723 TWPartition* SDext = Find_Partition_By_Path("/sd-ext");
1724 if (SDext != NULL) {
1725 if (!SDext->UnMount(true))
1726 return false;
1727 }
1728 system("umount \"$SWAPPATH\"");
1729 Device = SDCard->Actual_Block_Device;
1730 // Just use the root block device
1731 Device.resize(strlen("/dev/block/mmcblkX"));
1732
1733 // Find the size of the block device:
1734 fp = fopen("/proc/partitions", "rt");
1735 if (fp == NULL) {
1736 LOGE("Unable to open /proc/partitions\n");
1737 return false;
1738 }
1739
1740 while (fgets(line, sizeof(line), fp) != NULL)
1741 {
1742 unsigned long major, minor, blocks;
1743 char device[512];
1744 char tmpString[64];
1745
1746 if (strlen(line) < 7 || line[0] == 'm') continue;
1747 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
1748
1749 tmpdevice = "/dev/block/";
1750 tmpdevice += device;
1751 if (tmpdevice == Device) {
1752 // Adjust block size to byte size
1753 total_size = (int)(blocks * 1024ULL / 1000000LLU);
1754 break;
1755 }
1756 }
1757 fclose(fp);
1758
1759 DataManager::GetValue("tw_sdext_size", ext);
1760 DataManager::GetValue("tw_swap_size", swap);
1761 DataManager::GetValue("tw_sdpart_file_system", ext_format);
1762 fat_size = total_size - ext - swap;
1763 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);
1764 memset(temp, 0, sizeof(temp));
1765 sprintf(temp, "%i", fat_size);
1766 fat_str = temp;
1767 memset(temp, 0, sizeof(temp));
1768 sprintf(temp, "%i", fat_size + ext);
1769 ext_str = temp;
1770 memset(temp, 0, sizeof(temp));
1771 sprintf(temp, "%i", fat_size + ext + swap);
1772 swap_str = temp;
1773 if (ext + swap > total_size) {
1774 LOGE("EXT + Swap size is larger than sdcard size.\n");
1775 return false;
1776 }
1777 ui_print("Removing partition table...\n");
1778 Command = "parted -s " + Device + " mklabel msdos";
1779 LOGI("Command is: '%s'\n", Command.c_str());
1780 if (system(Command.c_str()) != 0) {
1781 LOGE("Unable to remove partition table.\n");
1782 Update_System_Details();
1783 return false;
1784 }
1785 ui_print("Creating FAT32 partition...\n");
1786 Command = "parted " + Device + " mkpartfs primary fat32 0 " + fat_str + "MB";
1787 LOGI("Command is: '%s'\n", Command.c_str());
1788 if (system(Command.c_str()) != 0) {
1789 LOGE("Unable to create FAT32 partition.\n");
1790 return false;
1791 }
1792 if (ext > 0) {
1793 ui_print("Creating EXT partition...\n");
1794 Command = "parted " + Device + " mkpartfs primary ext2 " + fat_str + "MB " + ext_str + "MB";
1795 LOGI("Command is: '%s'\n", Command.c_str());
1796 if (system(Command.c_str()) != 0) {
1797 LOGE("Unable to create EXT partition.\n");
1798 Update_System_Details();
1799 return false;
1800 }
1801 }
1802 if (swap > 0) {
1803 ui_print("Creating swap partition...\n");
1804 Command = "parted " + Device + " mkpartfs primary linux-swap " + ext_str + "MB " + swap_str + "MB";
1805 LOGI("Command is: '%s'\n", Command.c_str());
1806 if (system(Command.c_str()) != 0) {
1807 LOGE("Unable to create swap partition.\n");
1808 Update_System_Details();
1809 return false;
1810 }
1811 }
1812 // recreate TWRP folder and rewrite settings - these will be gone after sdcard is partitioned
1813#ifdef TW_EXTERNAL_STORAGE_PATH
1814 Mount_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1);
1815 DataManager::GetValue(TW_EXTERNAL_PATH, sd_path);
1816 memset(mkdir_path, 0, sizeof(mkdir_path));
1817 sprintf(mkdir_path, "%s/TWRP", sd_path.c_str());
1818#else
1819 Mount_By_Path("/sdcard", 1);
1820 strcpy(mkdir_path, "/sdcard/TWRP");
1821#endif
1822 mkdir(mkdir_path, 0777);
1823 DataManager::Flush();
1824#ifdef TW_EXTERNAL_STORAGE_PATH
1825 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1826 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1827 DataManager::SetValue(TW_ZIP_LOCATION_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1828#else
1829 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, "/sdcard");
1830 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1831 DataManager::SetValue(TW_ZIP_LOCATION_VAR, "/sdcard");
1832#endif
1833 if (ext > 0) {
1834 if (SDext == NULL) {
1835 LOGE("Unable to locate sd-ext partition.\n");
1836 return false;
1837 }
1838 Command = "mke2fs -t " + ext_format + " -m 0 " + SDext->Actual_Block_Device;
1839 ui_print("Formatting sd-ext as %s...\n", ext_format.c_str());
1840 LOGI("Formatting sd-ext after partitioning, command: '%s'\n", Command.c_str());
1841 system(Command.c_str());
1842 }
1843
1844 Update_System_Details();
1845 ui_print("Partitioning complete.\n");
1846 return true;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001847}