blob: a58900c6ee00bd68e714d386c4ccfc3fc850cee0 [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
2 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/stat.h>
23#include <sys/vfs.h>
24#include <unistd.h>
Dees_Troy5bf43922012-09-07 16:07:55 -040025#include <vector>
Dees_Troy63c8df72012-09-10 14:02:05 -040026#include <dirent.h>
27#include <time.h>
Dees_Troy8170a922012-09-18 15:40:25 -040028#include <errno.h>
29#include <fcntl.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050030#include <iostream>
31#include <iomanip>
Dees_Troy51a0e822012-09-05 15:24:24 -040032#include "variables.h"
Dees_Troy2673cec2013-04-02 20:22:16 +000033#include "twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040034#include "partitions.hpp"
Dees_Troy5bf43922012-09-07 16:07:55 -040035#include "data.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040036#include "twrp-functions.hpp"
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -040037#include "fixPermissions.hpp"
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -050038#include "twrpDigest.hpp"
bigbiff bigbiff34684ff2013-12-01 21:03:45 -050039#include "twrpDU.hpp"
Dees_Troy38bd7602012-09-14 13:33:53 -040040
Dees_Troy5bf43922012-09-07 16:07:55 -040041#ifdef TW_INCLUDE_CRYPTO
42 #ifdef TW_INCLUDE_JB_CRYPTO
43 #include "crypto/jb/cryptfs.h"
44 #else
45 #include "crypto/ics/cryptfs.h"
46 #endif
47 #include "cutils/properties.h"
48#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040049
bigbiff bigbiff34684ff2013-12-01 21:03:45 -050050TWPartitionManager::TWPartitionManager(void) {
51}
52
Dees_Troy51a0e822012-09-05 15:24:24 -040053int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -040054 FILE *fstabFile;
55 char fstab_line[MAX_FSTAB_LINE_LENGTH];
Dees_Troya13d74f2013-03-24 08:54:55 -050056 bool Found_Settings_Storage = false;
Dees_Troy5bf43922012-09-07 16:07:55 -040057
58 fstabFile = fopen(Fstab_Filename.c_str(), "rt");
59 if (fstabFile == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +000060 LOGERR("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -040061 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)) {
Dees_Troya13d74f2013-03-24 08:54:55 -050076 if (!Found_Settings_Storage && partition->Is_Settings_Storage) {
77 Found_Settings_Storage = true;
78 Partitions.push_back(partition);
79 DataManager::SetValue("tw_settings_path", partition->Storage_Path);
80 DataManager::SetValue("tw_storage_path", partition->Storage_Path);
Dees_Troy2673cec2013-04-02 20:22:16 +000081 LOGINFO("Settings storage is '%s'\n", partition->Storage_Path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -050082 } else {
83 partition->Is_Settings_Storage = false;
84 Partitions.push_back(partition);
85 }
Dees_Troy5bf43922012-09-07 16:07:55 -040086 } else {
87 delete partition;
88 }
89 }
90 fclose(fstabFile);
Dees_Troya13d74f2013-03-24 08:54:55 -050091 if (!Found_Settings_Storage) {
92 std::vector<TWPartition*>::iterator iter;
93 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
94 if ((*iter)->Is_Storage) {
95 (*iter)->Is_Settings_Storage = true;
96 Found_Settings_Storage = true;
97 DataManager::SetValue("tw_settings_path", (*iter)->Storage_Path);
98 DataManager::SetValue("tw_storage_path", (*iter)->Storage_Path);
Dees_Troy2673cec2013-04-02 20:22:16 +000099 LOGINFO("Settings storage is '%s'\n", (*iter)->Storage_Path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500100 break;
101 }
102 }
103 if (!Found_Settings_Storage)
Dees_Troy2673cec2013-04-02 20:22:16 +0000104 LOGERR("Unable to locate storage partition for storing settings file.\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500105 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400106 if (!Write_Fstab()) {
107 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000108 LOGERR("Error creating fstab\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400109 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000110 LOGINFO("Error creating fstab\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400111 }
Dees_Troy51127312012-09-08 13:08:49 -0400112 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400113 UnMount_Main_Partitions();
Dees_Troy5bf43922012-09-07 16:07:55 -0400114 return true;
115}
116
117int TWPartitionManager::Write_Fstab(void) {
118 FILE *fp;
119 std::vector<TWPartition*>::iterator iter;
120 string Line;
121
122 fp = fopen("/etc/fstab", "w");
123 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000124 LOGINFO("Can not open /etc/fstab.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -0400125 return false;
126 }
Dees_Troy63c8df72012-09-10 14:02:05 -0400127 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -0400128 if ((*iter)->Can_Be_Mounted) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400129 Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw\n";
Dees_Troy5bf43922012-09-07 16:07:55 -0400130 fputs(Line.c_str(), fp);
Dees_Troy91862e62013-04-04 23:48:21 +0000131 }
132 // Handle subpartition tracking
133 if ((*iter)->Is_SubPartition) {
134 TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
135 if (ParentPartition)
136 ParentPartition->Has_SubPartition = true;
137 else
138 LOGERR("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400139 }
140 }
141 fclose(fp);
142 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400143}
144
Dees_Troy8170a922012-09-18 15:40:25 -0400145void TWPartitionManager::Output_Partition_Logging(void) {
146 std::vector<TWPartition*>::iterator iter;
147
148 printf("\n\nPartition Logs:\n");
149 for (iter = Partitions.begin(); iter != Partitions.end(); iter++)
150 Output_Partition((*iter));
151}
152
153void TWPartitionManager::Output_Partition(TWPartition* Part) {
154 unsigned long long mb = 1048576;
155
Gary Peck004d48b2012-11-21 16:28:18 -0800156 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 -0400157 if (Part->Can_Be_Mounted) {
Gary Peck004d48b2012-11-21 16:28:18 -0800158 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 -0400159 }
Gary Peck004d48b2012-11-21 16:28:18 -0800160 printf("\n Flags: ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500161 if (Part->Can_Be_Mounted)
162 printf("Can_Be_Mounted ");
Gary Peck004d48b2012-11-21 16:28:18 -0800163 if (Part->Can_Be_Wiped)
164 printf("Can_Be_Wiped ");
Hashcodedabfd492013-08-29 22:45:30 -0700165 if (Part->Use_Rm_Rf)
166 printf("Use_Rm_Rf ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500167 if (Part->Can_Be_Backed_Up)
168 printf("Can_Be_Backed_Up ");
Gary Peck004d48b2012-11-21 16:28:18 -0800169 if (Part->Wipe_During_Factory_Reset)
170 printf("Wipe_During_Factory_Reset ");
171 if (Part->Wipe_Available_in_GUI)
172 printf("Wipe_Available_in_GUI ");
173 if (Part->Is_SubPartition)
174 printf("Is_SubPartition ");
175 if (Part->Has_SubPartition)
176 printf("Has_SubPartition ");
177 if (Part->Removable)
178 printf("Removable ");
179 if (Part->Is_Present)
180 printf("IsPresent ");
181 if (Part->Can_Be_Encrypted)
182 printf("Can_Be_Encrypted ");
183 if (Part->Is_Encrypted)
184 printf("Is_Encrypted ");
185 if (Part->Is_Decrypted)
186 printf("Is_Decrypted ");
187 if (Part->Has_Data_Media)
188 printf("Has_Data_Media ");
Dees_Troy83bd4832013-05-04 12:39:56 +0000189 if (Part->Can_Encrypt_Backup)
190 printf("Can_Encrypt_Backup ");
191 if (Part->Use_Userdata_Encryption)
192 printf("Use_Userdata_Encryption ");
Gary Peck004d48b2012-11-21 16:28:18 -0800193 if (Part->Has_Android_Secure)
194 printf("Has_Android_Secure ");
195 if (Part->Is_Storage)
196 printf("Is_Storage ");
Dees_Troya13d74f2013-03-24 08:54:55 -0500197 if (Part->Is_Settings_Storage)
198 printf("Is_Settings_Storage ");
Dees_Troy68cab492012-12-12 19:29:35 +0000199 if (Part->Ignore_Blkid)
200 printf("Ignore_Blkid ");
Dees_Troy16c2b312013-01-15 16:51:18 +0000201 if (Part->Retain_Layout_Version)
202 printf("Retain_Layout_Version ");
Gary Peck004d48b2012-11-21 16:28:18 -0800203 printf("\n");
204 if (!Part->SubPartition_Of.empty())
205 printf(" SubPartition_Of: %s\n", Part->SubPartition_Of.c_str());
206 if (!Part->Symlink_Path.empty())
207 printf(" Symlink_Path: %s\n", Part->Symlink_Path.c_str());
208 if (!Part->Symlink_Mount_Point.empty())
209 printf(" Symlink_Mount_Point: %s\n", Part->Symlink_Mount_Point.c_str());
210 if (!Part->Primary_Block_Device.empty())
211 printf(" Primary_Block_Device: %s\n", Part->Primary_Block_Device.c_str());
212 if (!Part->Alternate_Block_Device.empty())
213 printf(" Alternate_Block_Device: %s\n", Part->Alternate_Block_Device.c_str());
214 if (!Part->Decrypted_Block_Device.empty())
215 printf(" Decrypted_Block_Device: %s\n", Part->Decrypted_Block_Device.c_str());
216 if (Part->Length != 0)
217 printf(" Length: %i\n", Part->Length);
218 if (!Part->Display_Name.empty())
219 printf(" Display_Name: %s\n", Part->Display_Name.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500220 if (!Part->Storage_Name.empty())
221 printf(" Storage_Name: %s\n", Part->Storage_Name.c_str());
Gary Peck004d48b2012-11-21 16:28:18 -0800222 if (!Part->Backup_Path.empty())
223 printf(" Backup_Path: %s\n", Part->Backup_Path.c_str());
224 if (!Part->Backup_Name.empty())
225 printf(" Backup_Name: %s\n", Part->Backup_Name.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500226 if (!Part->Backup_Display_Name.empty())
227 printf(" Backup_Display_Name: %s\n", Part->Backup_Display_Name.c_str());
Gary Peck004d48b2012-11-21 16:28:18 -0800228 if (!Part->Backup_FileName.empty())
229 printf(" Backup_FileName: %s\n", Part->Backup_FileName.c_str());
230 if (!Part->Storage_Path.empty())
231 printf(" Storage_Path: %s\n", Part->Storage_Path.c_str());
232 if (!Part->Current_File_System.empty())
233 printf(" Current_File_System: %s\n", Part->Current_File_System.c_str());
234 if (!Part->Fstab_File_System.empty())
235 printf(" Fstab_File_System: %s\n", Part->Fstab_File_System.c_str());
236 if (Part->Format_Block_Size != 0)
237 printf(" Format_Block_Size: %i\n", Part->Format_Block_Size);
Dees_Troy094207a2012-09-26 12:00:39 -0400238 if (!Part->MTD_Name.empty())
239 printf(" MTD_Name: %s\n", Part->MTD_Name.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400240 string back_meth = Part->Backup_Method_By_Name();
241 printf(" Backup_Method: %s\n\n", back_meth.c_str());
Hashcode62bd9e02013-11-19 21:59:42 -0800242 if (Part->Mount_Flags || !Part->Mount_Options.empty())
243 printf(" Mount_Flags=0x%8x, Mount_Options=%s\n", Part->Mount_Flags, Part->Mount_Options.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400244}
245
Dees_Troy51a0e822012-09-05 15:24:24 -0400246int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400247 std::vector<TWPartition*>::iterator iter;
248 int ret = false;
249 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400250 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400251
Dees_Troyd93bda52013-07-03 19:55:19 +0000252 if (Local_Path == "/tmp" || Local_Path == "/")
Dees_Troy43d8b002012-09-17 16:00:01 -0400253 return true;
254
Dees_Troy5bf43922012-09-07 16:07:55 -0400255 // Iterate through all partitions
256 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400257 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400258 ret = (*iter)->Mount(Display_Error);
259 found = true;
Dees_Troy51127312012-09-08 13:08:49 -0400260 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
Dees_Troy5bf43922012-09-07 16:07:55 -0400261 (*iter)->Mount(Display_Error);
Dees_Troy51127312012-09-08 13:08:49 -0400262 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400263 }
264 if (found) {
265 return ret;
266 } else if (Display_Error) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000267 LOGERR("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400268 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000269 LOGINFO("Mount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400270 }
271 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400272}
273
274int TWPartitionManager::Mount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400275 TWPartition* Part = Find_Partition_By_Block(Block);
Dees_Troy5bf43922012-09-07 16:07:55 -0400276
Dees_Troy51127312012-09-08 13:08:49 -0400277 if (Part) {
278 if (Part->Has_SubPartition) {
279 std::vector<TWPartition*>::iterator subpart;
280
281 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
282 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
283 (*subpart)->Mount(Display_Error);
284 }
285 return Part->Mount(Display_Error);
286 } else
287 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400288 }
289 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000290 LOGERR("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400291 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000292 LOGINFO("Mount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400293 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400294}
295
296int TWPartitionManager::Mount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400297 TWPartition* Part = Find_Partition_By_Name(Name);
Dees_Troy5bf43922012-09-07 16:07:55 -0400298
Dees_Troy51127312012-09-08 13:08:49 -0400299 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)->Mount(Display_Error);
306 }
307 return Part->Mount(Display_Error);
308 } else
309 return Part->Mount(Display_Error);
Dees_Troy5bf43922012-09-07 16:07:55 -0400310 }
311 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000312 LOGERR("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400313 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000314 LOGINFO("Mount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy5bf43922012-09-07 16:07:55 -0400315 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400316}
317
318int TWPartitionManager::UnMount_By_Path(string Path, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400319 std::vector<TWPartition*>::iterator iter;
320 int ret = false;
321 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -0400322 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy51127312012-09-08 13:08:49 -0400323
324 // Iterate through all partitions
325 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400326 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troy51127312012-09-08 13:08:49 -0400327 ret = (*iter)->UnMount(Display_Error);
328 found = true;
329 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
330 (*iter)->UnMount(Display_Error);
331 }
332 }
333 if (found) {
334 return ret;
335 } else if (Display_Error) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000336 LOGERR("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400337 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000338 LOGINFO("UnMount: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400339 }
340 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400341}
342
343int TWPartitionManager::UnMount_By_Block(string Block, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400344 TWPartition* Part = Find_Partition_By_Block(Block);
345
346 if (Part) {
347 if (Part->Has_SubPartition) {
348 std::vector<TWPartition*>::iterator subpart;
349
350 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
351 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
352 (*subpart)->UnMount(Display_Error);
353 }
354 return Part->UnMount(Display_Error);
355 } else
356 return Part->UnMount(Display_Error);
357 }
358 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000359 LOGERR("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400360 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000361 LOGINFO("UnMount: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400362 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400363}
364
365int TWPartitionManager::UnMount_By_Name(string Name, bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400366 TWPartition* Part = Find_Partition_By_Name(Name);
367
368 if (Part) {
369 if (Part->Has_SubPartition) {
370 std::vector<TWPartition*>::iterator subpart;
371
372 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
373 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
374 (*subpart)->UnMount(Display_Error);
375 }
376 return Part->UnMount(Display_Error);
377 } else
378 return Part->UnMount(Display_Error);
379 }
380 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000381 LOGERR("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400382 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000383 LOGINFO("UnMount: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400384 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400385}
386
387int TWPartitionManager::Is_Mounted_By_Path(string Path) {
Dees_Troy51127312012-09-08 13:08:49 -0400388 TWPartition* Part = Find_Partition_By_Path(Path);
389
390 if (Part)
391 return Part->Is_Mounted();
392 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000393 LOGINFO("Is_Mounted: Unable to find partition for path '%s'\n", Path.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400394 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400395}
396
397int TWPartitionManager::Is_Mounted_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400398 TWPartition* Part = Find_Partition_By_Block(Block);
399
400 if (Part)
401 return Part->Is_Mounted();
402 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000403 LOGINFO("Is_Mounted: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400404 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400405}
406
407int TWPartitionManager::Is_Mounted_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400408 TWPartition* Part = Find_Partition_By_Name(Name);
409
410 if (Part)
411 return Part->Is_Mounted();
412 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000413 LOGINFO("Is_Mounted: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy51127312012-09-08 13:08:49 -0400414 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400415}
416
Dees_Troy5bf43922012-09-07 16:07:55 -0400417int TWPartitionManager::Mount_Current_Storage(bool Display_Error) {
Dees_Troy51127312012-09-08 13:08:49 -0400418 string current_storage_path = DataManager::GetCurrentStoragePath();
419
420 if (Mount_By_Path(current_storage_path, Display_Error)) {
421 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
422 if (FreeStorage)
423 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
424 return true;
425 }
426 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400427}
428
Dees_Troy5bf43922012-09-07 16:07:55 -0400429int TWPartitionManager::Mount_Settings_Storage(bool Display_Error) {
430 return Mount_By_Path(DataManager::GetSettingsStoragePath(), Display_Error);
431}
432
433TWPartition* TWPartitionManager::Find_Partition_By_Path(string Path) {
434 std::vector<TWPartition*>::iterator iter;
Dees_Troy38bd7602012-09-14 13:33:53 -0400435 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy5bf43922012-09-07 16:07:55 -0400436
437 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -0400438 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path))
Dees_Troy5bf43922012-09-07 16:07:55 -0400439 return (*iter);
440 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400441 return NULL;
442}
443
Dees_Troy5bf43922012-09-07 16:07:55 -0400444TWPartition* TWPartitionManager::Find_Partition_By_Block(string Block) {
Dees_Troy51127312012-09-08 13:08:49 -0400445 std::vector<TWPartition*>::iterator iter;
446
447 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -0400448 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 -0400449 return (*iter);
450 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400451 return NULL;
Dees_Troy5bf43922012-09-07 16:07:55 -0400452}
453
454TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) {
Dees_Troy51127312012-09-08 13:08:49 -0400455 std::vector<TWPartition*>::iterator iter;
456
457 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
458 if ((*iter)->Display_Name == Name)
459 return (*iter);
460 }
Dees_Troy5bf43922012-09-07 16:07:55 -0400461 return NULL;
462}
Dees_Troy51a0e822012-09-05 15:24:24 -0400463
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400464int TWPartitionManager::Check_Backup_Name(bool Display_Error) {
465 // Check the backup name to ensure that it is the correct size and contains only valid characters
466 // and that a backup with that name doesn't already exist
467 char backup_name[MAX_BACKUP_NAME_LEN];
468 char backup_loc[255], tw_image_dir[255];
469 int copy_size;
470 int index, cur_char;
471 string Backup_Name, Backup_Loc;
472
473 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
474 copy_size = Backup_Name.size();
475 // Check size
476 if (copy_size > MAX_BACKUP_NAME_LEN) {
477 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000478 LOGERR("Backup name is too long.\n");
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400479 return -2;
480 }
481
482 // Check each character
483 strncpy(backup_name, Backup_Name.c_str(), copy_size);
Dees_Troya13d74f2013-03-24 08:54:55 -0500484 if (copy_size == 1 && strncmp(backup_name, "0", 1) == 0)
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400485 return 0; // A "0" (zero) means to use the current timestamp for the backup name
486 for (index=0; index<copy_size; index++) {
487 cur_char = (int)backup_name[index];
488 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) {
489 // These are valid characters
490 // Numbers
491 // Upper case letters
492 // Lower case letters
493 // Space
494 // and -_.{}[]
495 } else {
496 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000497 LOGERR("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400498 return -3;
499 }
500 }
501
502 // Check to make sure that a backup with this name doesn't already exist
503 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Loc);
504 strcpy(backup_loc, Backup_Loc.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500505 sprintf(tw_image_dir,"%s/%s", backup_loc, Backup_Name.c_str());
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400506 if (TWFunc::Path_Exists(tw_image_dir)) {
507 if (Display_Error)
Dees_Troy2673cec2013-04-02 20:22:16 +0000508 LOGERR("A backup with this name already exists.\n");
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400509 return -4;
510 }
Dees_Troyc9ff7a32012-09-27 10:09:41 -0400511 // No problems found, return 0
512 return 0;
513}
514
Dees_Troy43d8b002012-09-17 16:00:01 -0400515bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename)
516{
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500517 string command;
Dees_Troy43d8b002012-09-17 16:00:01 -0400518 string Full_File = Backup_Folder + Backup_Filename;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500519 string result;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500520 twrpDigest md5sum;
Dees_Troy43d8b002012-09-17 16:00:01 -0400521
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500522 if (!generate_md5)
Dees_Troy43d8b002012-09-17 16:00:01 -0400523 return true;
Dees_Troy43d8b002012-09-17 16:00:01 -0400524
Dees_Troyb46a6842012-09-25 11:06:46 -0400525 TWFunc::GUI_Operation_Text(TW_GENERATE_MD5_TEXT, "Generating MD5");
Dees_Troy2673cec2013-04-02 20:22:16 +0000526 gui_print(" * Generating md5...\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400527
528 if (TWFunc::Path_Exists(Full_File)) {
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500529 md5sum.setfn(Backup_Folder + Backup_Filename);
530 if (md5sum.computeMD5() == 0)
531 if (md5sum.write_md5digest() == 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000532 gui_print(" * MD5 Created.\n");
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500533 else
534 return -1;
535 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000536 gui_print(" * MD5 Error!\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400537 } else {
538 char filename[512];
539 int index = 0;
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500540 string strfn;
Dees_Troy43d8b002012-09-17 16:00:01 -0400541 sprintf(filename, "%s%03i", Full_File.c_str(), index);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500542 strfn = filename;
Dees_Troy83bd4832013-05-04 12:39:56 +0000543 while (index < 1000) {
bigbiff bigbiff65a4c732013-03-15 15:17:50 -0400544 md5sum.setfn(filename);
Dees_Troy83bd4832013-05-04 12:39:56 +0000545 if (TWFunc::Path_Exists(filename)) {
546 if (md5sum.computeMD5() == 0) {
547 if (md5sum.write_md5digest() != 0)
548 {
549 gui_print(" * MD5 Error.\n");
550 return false;
551 }
552 } else {
553 gui_print(" * Error computing MD5.\n");
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500554 return false;
555 }
556 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400557 index++;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400558 sprintf(filename, "%s%03i", Full_File.c_str(), index);
bigbiff bigbiffcdcfee42013-02-27 21:11:26 -0500559 strfn = filename;
Dees_Troy43d8b002012-09-17 16:00:01 -0400560 }
561 if (index == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000562 LOGERR("Backup file: '%s' not found!\n", filename);
Dees_Troy43d8b002012-09-17 16:00:01 -0400563 return false;
564 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000565 gui_print(" * MD5 Created.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400566 }
567 return true;
568}
569
Dees_Troy093b7642012-09-21 15:59:38 -0400570bool 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 -0400571 time_t start, stop;
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500572 int img_bps;
573 unsigned long long file_bps;
Dees_Troy093b7642012-09-21 15:59:38 -0400574 unsigned long total_time, remain_time, section_time;
575 int use_compression, backup_time;
576 float pos;
Dees_Troy43d8b002012-09-17 16:00:01 -0400577
578 if (Part == NULL)
579 return true;
580
Dees_Troy093b7642012-09-21 15:59:38 -0400581 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
582
583 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
584 if (use_compression)
585 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
586 else
587 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
588
589 // We know the speed for both, how far into the whole backup are we, based on time
590 total_time = (*img_bytes / (unsigned long)img_bps) + (*file_bytes / (unsigned long)file_bps);
591 remain_time = (*img_bytes_remaining / (unsigned long)img_bps) + (*file_bytes_remaining / (unsigned long)file_bps);
592
593 pos = (total_time - remain_time) / (float) total_time;
Dees_Troy2673cec2013-04-02 20:22:16 +0000594 DataManager::SetProgress(pos);
Dees_Troy093b7642012-09-21 15:59:38 -0400595
Dees_Troy2673cec2013-04-02 20:22:16 +0000596 LOGINFO("Estimated Total time: %lu Estimated remaining time: %lu\n", total_time, remain_time);
Dees_Troy093b7642012-09-21 15:59:38 -0400597
598 // And get the time
599 if (Part->Backup_Method == 1)
600 section_time = Part->Backup_Size / file_bps;
601 else
602 section_time = Part->Backup_Size / img_bps;
603
604 // Set the position
605 pos = section_time / (float) total_time;
Dees_Troy2673cec2013-04-02 20:22:16 +0000606 DataManager::ShowProgress(pos, section_time);
Dees_Troy093b7642012-09-21 15:59:38 -0400607
Dees_Troy43d8b002012-09-17 16:00:01 -0400608 time(&start);
609
610 if (Part->Backup(Backup_Folder)) {
Dees_Troy8170a922012-09-18 15:40:25 -0400611 if (Part->Has_SubPartition) {
612 std::vector<TWPartition*>::iterator subpart;
613
614 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500615 if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
Dees_Troy8170a922012-09-18 15:40:25 -0400616 if (!(*subpart)->Backup(Backup_Folder))
617 return false;
Dees_Troy2727b992013-08-14 20:09:30 +0000618 sync();
619 sync();
Dees_Troy8170a922012-09-18 15:40:25 -0400620 if (!Make_MD5(generate_md5, Backup_Folder, (*subpart)->Backup_FileName))
621 return false;
Dees_Troy093b7642012-09-21 15:59:38 -0400622 if (Part->Backup_Method == 1) {
623 *file_bytes_remaining -= (*subpart)->Backup_Size;
624 } else {
625 *img_bytes_remaining -= (*subpart)->Backup_Size;
626 }
Dees_Troy8170a922012-09-18 15:40:25 -0400627 }
628 }
629 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400630 time(&stop);
Dees_Troy093b7642012-09-21 15:59:38 -0400631 backup_time = (int) difftime(stop, start);
Dees_Troy2673cec2013-04-02 20:22:16 +0000632 LOGINFO("Partition Backup time: %d\n", backup_time);
Dees_Troy43d8b002012-09-17 16:00:01 -0400633 if (Part->Backup_Method == 1) {
634 *file_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400635 *file_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400636 } else {
637 *img_bytes_remaining -= Part->Backup_Size;
Dees_Troy093b7642012-09-21 15:59:38 -0400638 *img_time += backup_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400639 }
640 return Make_MD5(generate_md5, Backup_Folder, Part->Backup_FileName);
641 } else {
642 return false;
643 }
644}
645
646int TWPartitionManager::Run_Backup(void) {
647 int check, do_md5, partition_count = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500648 string Backup_Folder, Backup_Name, Full_Backup_Path, Backup_List, backup_path;
Dees_Troy8170a922012-09-18 15:40:25 -0400649 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 -0400650 unsigned long img_time = 0, file_time = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500651 TWPartition* backup_part = NULL;
Dees_Troy43d8b002012-09-17 16:00:01 -0400652 TWPartition* storage = NULL;
Dees_Troy8170a922012-09-18 15:40:25 -0400653 std::vector<TWPartition*>::iterator subpart;
Dees_Troy43d8b002012-09-17 16:00:01 -0400654 struct tm *t;
655 time_t start, stop, seconds, total_start, total_stop;
Dees_Troya13d74f2013-03-24 08:54:55 -0500656 size_t start_pos = 0, end_pos = 0;
Dees_Troy43d8b002012-09-17 16:00:01 -0400657 seconds = time(0);
658 t = localtime(&seconds);
659
660 time(&total_start);
661
662 Update_System_Details();
663
664 if (!Mount_Current_Storage(true))
665 return false;
666
667 DataManager::GetValue(TW_SKIP_MD5_GENERATE_VAR, do_md5);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400668 if (do_md5 == 0)
Dees_Troy43d8b002012-09-17 16:00:01 -0400669 do_md5 = true;
Dees_Troyc5865ab2012-09-24 15:08:04 -0400670 else
671 do_md5 = false;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400672
Dees_Troy43d8b002012-09-17 16:00:01 -0400673 DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Folder);
674 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
Dees Troyb21cc642013-09-10 17:36:41 +0000675 if (Backup_Name == "(Current Date)") {
676 Backup_Name = TWFunc::Get_Current_Date();
677 } else if (Backup_Name == "(Auto Generate)" || Backup_Name == "0" || Backup_Name.empty()) {
678 TWFunc::Auto_Generate_Backup_Name();
679 DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
Dees_Troy43d8b002012-09-17 16:00:01 -0400680 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000681 LOGINFO("Backup Name is: '%s'\n", Backup_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400682 Full_Backup_Path = Backup_Folder + "/" + Backup_Name + "/";
Dees_Troy2673cec2013-04-02 20:22:16 +0000683 LOGINFO("Full_Backup_Path is: '%s'\n", Full_Backup_Path.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400684
Dees_Troy2673cec2013-04-02 20:22:16 +0000685 LOGINFO("Calculating backup details...\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500686 DataManager::GetValue("tw_backup_list", Backup_List);
687 if (!Backup_List.empty()) {
688 end_pos = Backup_List.find(";", start_pos);
689 while (end_pos != string::npos && start_pos < Backup_List.size()) {
690 backup_path = Backup_List.substr(start_pos, end_pos - start_pos);
691 backup_part = Find_Partition_By_Path(backup_path);
692 if (backup_part != NULL) {
693 partition_count++;
694 if (backup_part->Backup_Method == 1)
695 file_bytes += backup_part->Backup_Size;
696 else
697 img_bytes += backup_part->Backup_Size;
698 if (backup_part->Has_SubPartition) {
699 std::vector<TWPartition*>::iterator subpart;
700
701 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
Dees_Troy9e0b71c2013-04-08 13:35:37 +0000702 if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_Present && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == backup_part->Mount_Point) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500703 partition_count++;
704 if ((*subpart)->Backup_Method == 1)
705 file_bytes += (*subpart)->Backup_Size;
706 else
707 img_bytes += (*subpart)->Backup_Size;
708 }
709 }
Dees_Troy8170a922012-09-18 15:40:25 -0400710 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500711 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000712 LOGERR("Unable to locate '%s' partition for backup calculations.\n", backup_path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -0400713 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500714 start_pos = end_pos + 1;
715 end_pos = Backup_List.find(";", start_pos);
Dees_Troy43d8b002012-09-17 16:00:01 -0400716 }
717 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400718
719 if (partition_count == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000720 gui_print("No partitions selected for backup.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400721 return false;
722 }
723 total_bytes = file_bytes + img_bytes;
Dees_Troy2673cec2013-04-02 20:22:16 +0000724 gui_print(" * Total number of partitions to back up: %d\n", partition_count);
725 gui_print(" * Total size of all data: %lluMB\n", total_bytes / 1024 / 1024);
Dees_Troy43d8b002012-09-17 16:00:01 -0400726 storage = Find_Partition_By_Path(DataManager::GetCurrentStoragePath());
727 if (storage != NULL) {
728 free_space = storage->Free;
Dees_Troy2673cec2013-04-02 20:22:16 +0000729 gui_print(" * Available space: %lluMB\n", free_space / 1024 / 1024);
Dees_Troy43d8b002012-09-17 16:00:01 -0400730 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000731 LOGERR("Unable to locate storage device.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400732 return false;
733 }
Dees_Troyd4b22b02013-01-18 17:17:58 +0000734 if (free_space - (32 * 1024 * 1024) < total_bytes) {
Dees_Troy43d8b002012-09-17 16:00:01 -0400735 // We require an extra 32MB just in case
Dees_Troy2673cec2013-04-02 20:22:16 +0000736 LOGERR("Not enough free space on storage.\n");
Dees_Troy43d8b002012-09-17 16:00:01 -0400737 return false;
738 }
739 img_bytes_remaining = img_bytes;
740 file_bytes_remaining = file_bytes;
741
Dees_Troy2673cec2013-04-02 20:22:16 +0000742 gui_print("\n[BACKUP STARTED]\n");
743 gui_print(" * Backup Folder: %s\n", Full_Backup_Path.c_str());
Dees_Troyd4b22b02013-01-18 17:17:58 +0000744 if (!TWFunc::Recursive_Mkdir(Full_Backup_Path)) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000745 LOGERR("Failed to make backup folder.\n");
Dees_Troyd4b22b02013-01-18 17:17:58 +0000746 return false;
747 }
748
Dees_Troy2673cec2013-04-02 20:22:16 +0000749 DataManager::SetProgress(0.0);
Dees_Troy093b7642012-09-21 15:59:38 -0400750
Dees_Troya13d74f2013-03-24 08:54:55 -0500751 start_pos = 0;
752 end_pos = Backup_List.find(";", start_pos);
753 while (end_pos != string::npos && start_pos < Backup_List.size()) {
754 backup_path = Backup_List.substr(start_pos, end_pos - start_pos);
755 backup_part = Find_Partition_By_Path(backup_path);
756 if (backup_part != NULL) {
757 if (!Backup_Partition(backup_part, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes))
758 return false;
759 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000760 LOGERR("Unable to locate '%s' partition for backup process.\n", backup_path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500761 }
762 start_pos = end_pos + 1;
763 end_pos = Backup_List.find(";", start_pos);
764 }
Dees_Troy43d8b002012-09-17 16:00:01 -0400765
766 // Average BPS
767 if (img_time == 0)
768 img_time = 1;
769 if (file_time == 0)
770 file_time = 1;
Dees_Troy093b7642012-09-21 15:59:38 -0400771 int img_bps = (int)img_bytes / (int)img_time;
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500772 unsigned long long file_bps = file_bytes / (int)file_time;
Dees_Troy43d8b002012-09-17 16:00:01 -0400773
Dees_Troy2673cec2013-04-02 20:22:16 +0000774 gui_print("Average backup rate for file systems: %llu MB/sec\n", (file_bps / (1024 * 1024)));
775 gui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));
Dees_Troy43d8b002012-09-17 16:00:01 -0400776
777 time(&total_stop);
778 int total_time = (int) difftime(total_stop, total_start);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500779 uint64_t actual_backup_size = du.Get_Folder_Size(Full_Backup_Path);
Dees_Troy43d8b002012-09-17 16:00:01 -0400780 actual_backup_size /= (1024LLU * 1024LLU);
781
bigbiff bigbiff2c57d782013-02-19 10:09:21 -0500782 int prev_img_bps, use_compression;
783 unsigned long long prev_file_bps;
Dees_Troy093b7642012-09-21 15:59:38 -0400784 DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, prev_img_bps);
785 img_bps += (prev_img_bps * 4);
786 img_bps /= 5;
787
788 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
789 if (use_compression)
790 DataManager::GetValue(TW_BACKUP_AVG_FILE_COMP_RATE, prev_file_bps);
791 else
792 DataManager::GetValue(TW_BACKUP_AVG_FILE_RATE, prev_file_bps);
793 file_bps += (prev_file_bps * 4);
794 file_bps /= 5;
795
796 DataManager::SetValue(TW_BACKUP_AVG_IMG_RATE, img_bps);
797 if (use_compression)
798 DataManager::SetValue(TW_BACKUP_AVG_FILE_COMP_RATE, file_bps);
799 else
800 DataManager::SetValue(TW_BACKUP_AVG_FILE_RATE, file_bps);
801
Dees_Troy2673cec2013-04-02 20:22:16 +0000802 gui_print("[%llu MB TOTAL BACKED UP]\n", actual_backup_size);
Dees_Troy43d8b002012-09-17 16:00:01 -0400803 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400804 UnMount_Main_Partitions();
Dees_Troy2673cec2013-04-02 20:22:16 +0000805 gui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
Dees_Troy3f5c4e82013-02-01 15:16:59 +0000806 string backup_log = Full_Backup_Path + "recovery.log";
807 TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644);
808 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400809}
810
Dees_Troy093b7642012-09-21 15:59:38 -0400811bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Name, int partition_count) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400812 time_t Start, Stop;
813 time(&Start);
Dees_Troy2673cec2013-04-02 20:22:16 +0000814 DataManager::ShowProgress(1.0 / (float)partition_count, 150);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400815 if (!Part->Restore(Restore_Name))
816 return false;
Dees_Troy8170a922012-09-18 15:40:25 -0400817 if (Part->Has_SubPartition) {
818 std::vector<TWPartition*>::iterator subpart;
819
820 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
821 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) {
822 if (!(*subpart)->Restore(Restore_Name))
823 return false;
824 }
825 }
826 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400827 time(&Stop);
Dees_Troy2673cec2013-04-02 20:22:16 +0000828 gui_print("[%s done (%d seconds)]\n\n", Part->Backup_Display_Name.c_str(), (int)difftime(Stop, Start));
Dees_Troy4a2a1262012-09-18 09:33:47 -0400829 return true;
830}
831
Dees_Troy51a0e822012-09-05 15:24:24 -0400832int TWPartitionManager::Run_Restore(string Restore_Name) {
Dees_Troy4a2a1262012-09-18 09:33:47 -0400833 int check_md5, check, partition_count = 0;
Dees_Troya13d74f2013-03-24 08:54:55 -0500834 TWPartition* restore_part = NULL;
Dees_Troy4a2a1262012-09-18 09:33:47 -0400835 time_t rStart, rStop;
836 time(&rStart);
Dees_Troya13d74f2013-03-24 08:54:55 -0500837 string Restore_List, restore_path;
838 size_t start_pos = 0, end_pos;
Dees_Troy43d8b002012-09-17 16:00:01 -0400839
Dees_Troy2673cec2013-04-02 20:22:16 +0000840 gui_print("\n[RESTORE STARTED]\n\n");
841 gui_print("Restore folder: '%s'\n", Restore_Name.c_str());
Dees_Troy43d8b002012-09-17 16:00:01 -0400842
Dees_Troy4a2a1262012-09-18 09:33:47 -0400843 if (!Mount_Current_Storage(true))
844 return false;
845
846 DataManager::GetValue(TW_SKIP_MD5_CHECK_VAR, check_md5);
Dees_Troya13d74f2013-03-24 08:54:55 -0500847 if (check_md5 > 0) {
848 // Check MD5 files first before restoring to ensure that all of them match before starting a restore
849 TWFunc::GUI_Operation_Text(TW_VERIFY_MD5_TEXT, "Verifying MD5");
Dees_Troy2673cec2013-04-02 20:22:16 +0000850 gui_print("Verifying MD5...\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500851 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000852 gui_print("Skipping MD5 check based on user setting.\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500853 }
854 DataManager::GetValue("tw_restore_selected", Restore_List);
855 if (!Restore_List.empty()) {
856 end_pos = Restore_List.find(";", start_pos);
857 while (end_pos != string::npos && start_pos < Restore_List.size()) {
858 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
859 restore_part = Find_Partition_By_Path(restore_path);
860 if (restore_part != NULL) {
861 partition_count++;
862 if (check_md5 > 0 && !restore_part->Check_MD5(Restore_Name))
863 return false;
864 if (restore_part->Has_SubPartition) {
865 std::vector<TWPartition*>::iterator subpart;
866
867 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
868 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == restore_part->Mount_Point) {
869 if (!(*subpart)->Check_MD5(Restore_Name))
870 return false;
871 }
872 }
873 }
874 } else {
Dees_Troy59df9262013-06-19 14:53:57 -0500875 LOGERR("Unable to locate '%s' partition for restoring (restore list).\n", restore_path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500876 }
877 start_pos = end_pos + 1;
878 end_pos = Restore_List.find(";", start_pos);
Dees_Troy4a2a1262012-09-18 09:33:47 -0400879 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400880 }
Dees_Troy4a2a1262012-09-18 09:33:47 -0400881
882 if (partition_count == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000883 LOGERR("No partitions selected for restore.\n");
Dees_Troy4a2a1262012-09-18 09:33:47 -0400884 return false;
885 }
886
Dees_Troy2673cec2013-04-02 20:22:16 +0000887 gui_print("Restoring %i partitions...\n", partition_count);
888 DataManager::SetProgress(0.0);
Dees_Troya13d74f2013-03-24 08:54:55 -0500889 start_pos = 0;
890 if (!Restore_List.empty()) {
891 end_pos = Restore_List.find(";", start_pos);
892 while (end_pos != string::npos && start_pos < Restore_List.size()) {
893 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
894 restore_part = Find_Partition_By_Path(restore_path);
895 if (restore_part != NULL) {
896 partition_count++;
897 if (!Restore_Partition(restore_part, Restore_Name, partition_count))
898 return false;
899 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000900 LOGERR("Unable to locate '%s' partition for restoring.\n", restore_path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500901 }
902 start_pos = end_pos + 1;
903 end_pos = Restore_List.find(";", start_pos);
904 }
905 }
Dees_Troyb46a6842012-09-25 11:06:46 -0400906 TWFunc::GUI_Operation_Text(TW_UPDATE_SYSTEM_DETAILS_TEXT, "Updating System Details");
Dees_Troy43d8b002012-09-17 16:00:01 -0400907 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -0400908 UnMount_Main_Partitions();
Dees_Troy4a2a1262012-09-18 09:33:47 -0400909 time(&rStop);
Dees_Troy2673cec2013-04-02 20:22:16 +0000910 gui_print("[RESTORE COMPLETED IN %d SECONDS]\n\n",(int)difftime(rStop,rStart));
Dees_Troy63c8df72012-09-10 14:02:05 -0400911 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400912}
913
914void TWPartitionManager::Set_Restore_Files(string Restore_Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -0400915 // Start with the default values
Dees_Troya13d74f2013-03-24 08:54:55 -0500916 string Restore_List;
Dees_Troy83bd4832013-05-04 12:39:56 +0000917 bool get_date = true, check_encryption = true;
918
919 DataManager::SetValue("tw_restore_encrypted", 0);
Dees_Troy63c8df72012-09-10 14:02:05 -0400920
921 DIR* d;
922 d = opendir(Restore_Name.c_str());
923 if (d == NULL)
924 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000925 LOGERR("Error opening %s\n", Restore_Name.c_str());
Dees_Troy63c8df72012-09-10 14:02:05 -0400926 return;
927 }
928
929 struct dirent* de;
930 while ((de = readdir(d)) != NULL)
931 {
932 // Strip off three components
933 char str[256];
934 char* label;
935 char* fstype = NULL;
936 char* extn = NULL;
937 char* ptr;
938
939 strcpy(str, de->d_name);
940 if (strlen(str) <= 2)
941 continue;
942
943 if (get_date) {
944 char file_path[255];
945 struct stat st;
946
947 strcpy(file_path, Restore_Name.c_str());
948 strcat(file_path, "/");
949 strcat(file_path, str);
950 stat(file_path, &st);
951 string backup_date = ctime((const time_t*)(&st.st_mtime));
952 DataManager::SetValue(TW_RESTORE_FILE_DATE, backup_date);
953 get_date = false;
954 }
955
956 label = str;
957 ptr = label;
958 while (*ptr && *ptr != '.') ptr++;
959 if (*ptr == '.')
960 {
961 *ptr = 0x00;
962 ptr++;
963 fstype = ptr;
964 }
965 while (*ptr && *ptr != '.') ptr++;
966 if (*ptr == '.')
967 {
968 *ptr = 0x00;
969 ptr++;
970 extn = ptr;
971 }
972
Dees_Troy83bd4832013-05-04 12:39:56 +0000973 if (fstype == NULL || extn == NULL || strcmp(fstype, "log") == 0) continue;
Dees_Troya13d74f2013-03-24 08:54:55 -0500974 int extnlength = strlen(extn);
Dees_Troy83bd4832013-05-04 12:39:56 +0000975 if (extnlength != 3 && extnlength != 6) continue;
976 if (extnlength >= 3 && strncmp(extn, "win", 3) != 0) continue;
977 //if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
978
979 if (check_encryption) {
980 string filename = Restore_Name + "/";
981 filename += de->d_name;
982 if (TWFunc::Get_File_Type(filename) == 2) {
983 LOGINFO("'%s' is encrypted\n", filename.c_str());
984 DataManager::SetValue("tw_restore_encrypted", 1);
985 }
986 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500987 if (extnlength == 6 && strncmp(extn, "win000", 6) != 0) continue;
Dees_Troy63c8df72012-09-10 14:02:05 -0400988
989 TWPartition* Part = Find_Partition_By_Path(label);
990 if (Part == NULL)
991 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000992 LOGERR(" Unable to locate partition by backup name: '%s'\n", label);
Dees_Troy63c8df72012-09-10 14:02:05 -0400993 continue;
994 }
995
996 Part->Backup_FileName = de->d_name;
997 if (strlen(extn) > 3) {
998 Part->Backup_FileName.resize(Part->Backup_FileName.size() - strlen(extn) + 3);
999 }
1000
Dees_Troya13d74f2013-03-24 08:54:55 -05001001 Restore_List += Part->Backup_Path + ";";
Dees_Troy63c8df72012-09-10 14:02:05 -04001002 }
1003 closedir(d);
1004
Dees_Troya13d74f2013-03-24 08:54:55 -05001005 // Set the final value
1006 DataManager::SetValue("tw_restore_list", Restore_List);
1007 DataManager::SetValue("tw_restore_selected", Restore_List);
Dees_Troy51a0e822012-09-05 15:24:24 -04001008 return;
1009}
1010
1011int TWPartitionManager::Wipe_By_Path(string Path) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001012 std::vector<TWPartition*>::iterator iter;
1013 int ret = false;
1014 bool found = false;
Dees_Troy38bd7602012-09-14 13:33:53 -04001015 string Local_Path = TWFunc::Get_Root_Path(Path);
Dees_Troy63c8df72012-09-10 14:02:05 -04001016
1017 // Iterate through all partitions
1018 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy657c3092012-09-10 20:32:10 -04001019 if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
Dees_Troye58d5262012-09-21 12:27:57 -04001020 if (Path == "/and-sec")
1021 ret = (*iter)->Wipe_AndSec();
1022 else
1023 ret = (*iter)->Wipe();
Dees_Troy63c8df72012-09-10 14:02:05 -04001024 found = true;
1025 } else if ((*iter)->Is_SubPartition && (*iter)->SubPartition_Of == Local_Path) {
1026 (*iter)->Wipe();
1027 }
1028 }
1029 if (found) {
1030 return ret;
1031 } else
Dees_Troy2673cec2013-04-02 20:22:16 +00001032 LOGERR("Wipe: Unable to find partition for path '%s'\n", Local_Path.c_str());
Dees_Troy63c8df72012-09-10 14:02:05 -04001033 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001034}
1035
1036int TWPartitionManager::Wipe_By_Block(string Block) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001037 TWPartition* Part = Find_Partition_By_Block(Block);
1038
1039 if (Part) {
1040 if (Part->Has_SubPartition) {
1041 std::vector<TWPartition*>::iterator subpart;
1042
1043 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1044 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1045 (*subpart)->Wipe();
1046 }
1047 return Part->Wipe();
1048 } else
1049 return Part->Wipe();
1050 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001051 LOGERR("Wipe: Unable to find partition for block '%s'\n", Block.c_str());
Dees_Troy63c8df72012-09-10 14:02:05 -04001052 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001053}
1054
1055int TWPartitionManager::Wipe_By_Name(string Name) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001056 TWPartition* Part = Find_Partition_By_Name(Name);
1057
1058 if (Part) {
1059 if (Part->Has_SubPartition) {
1060 std::vector<TWPartition*>::iterator subpart;
1061
1062 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1063 if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point)
1064 (*subpart)->Wipe();
1065 }
1066 return Part->Wipe();
1067 } else
1068 return Part->Wipe();
1069 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001070 LOGERR("Wipe: Unable to find partition for name '%s'\n", Name.c_str());
Dees_Troy63c8df72012-09-10 14:02:05 -04001071 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -04001072}
1073
1074int TWPartitionManager::Factory_Reset(void) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001075 std::vector<TWPartition*>::iterator iter;
1076 int ret = true;
1077
1078 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001079 if ((*iter)->Wipe_During_Factory_Reset && (*iter)->Is_Present) {
Dees_Troy63c8df72012-09-10 14:02:05 -04001080 if (!(*iter)->Wipe())
1081 ret = false;
Dees_Troy094207a2012-09-26 12:00:39 -04001082 } else if ((*iter)->Has_Android_Secure) {
1083 if (!(*iter)->Wipe_AndSec())
1084 ret = false;
Dees_Troy63c8df72012-09-10 14:02:05 -04001085 }
1086 }
1087 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001088}
1089
Dees_Troy38bd7602012-09-14 13:33:53 -04001090int TWPartitionManager::Wipe_Dalvik_Cache(void) {
1091 struct stat st;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001092 vector <string> dir;
Dees_Troy38bd7602012-09-14 13:33:53 -04001093
1094 if (!Mount_By_Path("/data", true))
1095 return false;
1096
1097 if (!Mount_By_Path("/cache", true))
1098 return false;
1099
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001100 dir.push_back("/data/dalvik-cache");
1101 dir.push_back("/cache/dalvik-cache");
1102 dir.push_back("/cache/dc");
Dees_Troy2673cec2013-04-02 20:22:16 +00001103 gui_print("\nWiping Dalvik Cache Directories...\n");
Dees_Troya13d74f2013-03-24 08:54:55 -05001104 for (unsigned i = 0; i < dir.size(); ++i) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001105 if (stat(dir.at(i).c_str(), &st) == 0) {
1106 TWFunc::removeDir(dir.at(i), false);
Dees_Troy2673cec2013-04-02 20:22:16 +00001107 gui_print("Cleaned: %s...\n", dir.at(i).c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001108 }
1109 }
Dees_Troy38bd7602012-09-14 13:33:53 -04001110 TWPartition* sdext = Find_Partition_By_Path("/sd-ext");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001111 if (sdext && sdext->Is_Present && sdext->Mount(false))
1112 {
1113 if (stat("/sd-ext/dalvik-cache", &st) == 0)
1114 {
1115 TWFunc::removeDir("/sd-ext/dalvik-cache", false);
1116 gui_print("Cleaned: /sd-ext/dalvik-cache...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001117 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001118 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001119 gui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001120 return true;
1121}
1122
1123int TWPartitionManager::Wipe_Rotate_Data(void) {
1124 if (!Mount_By_Path("/data", true))
1125 return false;
1126
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001127 unlink("/data/misc/akmd*");
1128 unlink("/data/misc/rild*");
Dees_Troy2673cec2013-04-02 20:22:16 +00001129 gui_print("Rotation data wiped.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001130 return true;
1131}
1132
1133int TWPartitionManager::Wipe_Battery_Stats(void) {
1134 struct stat st;
1135
1136 if (!Mount_By_Path("/data", true))
1137 return false;
1138
1139 if (0 != stat("/data/system/batterystats.bin", &st)) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001140 gui_print("No Battery Stats Found. No Need To Wipe.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001141 } else {
1142 remove("/data/system/batterystats.bin");
Dees_Troy2673cec2013-04-02 20:22:16 +00001143 gui_print("Cleared battery stats.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001144 }
1145 return true;
1146}
1147
Dees_Troy2ff5a8d2012-09-26 14:53:02 -04001148int TWPartitionManager::Wipe_Android_Secure(void) {
1149 std::vector<TWPartition*>::iterator iter;
1150 int ret = false;
1151 bool found = false;
1152
1153 // Iterate through all partitions
1154 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1155 if ((*iter)->Has_Android_Secure) {
1156 ret = (*iter)->Wipe_AndSec();
1157 found = true;
1158 }
1159 }
1160 if (found) {
1161 return ret;
1162 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001163 LOGERR("No android secure partitions found.\n");
Dees_Troy2ff5a8d2012-09-26 14:53:02 -04001164 }
1165 return false;
1166}
1167
Dees_Troy38bd7602012-09-14 13:33:53 -04001168int TWPartitionManager::Format_Data(void) {
1169 TWPartition* dat = Find_Partition_By_Path("/data");
1170
1171 if (dat != NULL) {
1172 if (!dat->UnMount(true))
1173 return false;
1174
1175 return dat->Wipe_Encryption();
1176 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001177 LOGERR("Unable to locate /data.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001178 return false;
1179 }
1180 return false;
1181}
1182
1183int TWPartitionManager::Wipe_Media_From_Data(void) {
1184 TWPartition* dat = Find_Partition_By_Path("/data");
1185
1186 if (dat != NULL) {
1187 if (!dat->Has_Data_Media) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001188 LOGERR("This device does not have /data/media\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001189 return false;
1190 }
1191 if (!dat->Mount(true))
1192 return false;
1193
Dees_Troy2673cec2013-04-02 20:22:16 +00001194 gui_print("Wiping internal storage -- /data/media...\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001195 TWFunc::removeDir("/data/media", false);
1196 if (mkdir("/data/media", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
1197 return -1;
Dees_Troy38bd7602012-09-14 13:33:53 -04001198 if (dat->Has_Data_Media) {
1199 dat->Recreate_Media_Folder();
Dees_Troy74fb2e92013-04-15 14:35:47 +00001200 // Unmount and remount - slightly hackish way to ensure that the "/sdcard" folder is still mounted properly after wiping
1201 dat->UnMount(false);
1202 dat->Mount(false);
Dees_Troy38bd7602012-09-14 13:33:53 -04001203 }
1204 return true;
1205 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001206 LOGERR("Unable to locate /data.\n");
Dees_Troy38bd7602012-09-14 13:33:53 -04001207 return false;
1208 }
1209 return false;
1210}
1211
Dees_Troy51a0e822012-09-05 15:24:24 -04001212void TWPartitionManager::Refresh_Sizes(void) {
Dees_Troy51127312012-09-08 13:08:49 -04001213 Update_System_Details();
Dees_Troy51a0e822012-09-05 15:24:24 -04001214 return;
1215}
1216
1217void TWPartitionManager::Update_System_Details(void) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001218 std::vector<TWPartition*>::iterator iter;
Dees_Troy51127312012-09-08 13:08:49 -04001219 int data_size = 0;
Dees_Troy5bf43922012-09-07 16:07:55 -04001220
Dees_Troy2673cec2013-04-02 20:22:16 +00001221 gui_print("Updating partition details...\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001222 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy51127312012-09-08 13:08:49 -04001223 if ((*iter)->Can_Be_Mounted) {
1224 (*iter)->Update_Size(true);
1225 if ((*iter)->Mount_Point == "/system") {
1226 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1227 DataManager::SetValue(TW_BACKUP_SYSTEM_SIZE, backup_display_size);
1228 } else if ((*iter)->Mount_Point == "/data" || (*iter)->Mount_Point == "/datadata") {
1229 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
1230 } else if ((*iter)->Mount_Point == "/cache") {
1231 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1232 DataManager::SetValue(TW_BACKUP_CACHE_SIZE, backup_display_size);
1233 } else if ((*iter)->Mount_Point == "/sd-ext") {
1234 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1235 DataManager::SetValue(TW_BACKUP_SDEXT_SIZE, backup_display_size);
1236 if ((*iter)->Backup_Size == 0) {
1237 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 0);
1238 DataManager::SetValue(TW_BACKUP_SDEXT_VAR, 0);
1239 } else
1240 DataManager::SetValue(TW_HAS_SDEXT_PARTITION, 1);
Dees_Troye58d5262012-09-21 12:27:57 -04001241 } else if ((*iter)->Has_Android_Secure) {
Dees_Troy8170a922012-09-18 15:40:25 -04001242 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
Dees_Troye58d5262012-09-21 12:27:57 -04001243 DataManager::SetValue(TW_BACKUP_ANDSEC_SIZE, backup_display_size);
Dees_Troy8170a922012-09-18 15:40:25 -04001244 if ((*iter)->Backup_Size == 0) {
1245 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 0);
1246 DataManager::SetValue(TW_BACKUP_ANDSEC_VAR, 0);
1247 } else
1248 DataManager::SetValue(TW_HAS_ANDROID_SECURE, 1);
Dees_Troy2c50e182012-09-26 20:05:28 -04001249 } else if ((*iter)->Mount_Point == "/boot") {
1250 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1251 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
1252 if ((*iter)->Backup_Size == 0) {
1253 DataManager::SetValue("tw_has_boot_partition", 0);
1254 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
1255 } else
1256 DataManager::SetValue("tw_has_boot_partition", 1);
Dees_Troy51127312012-09-08 13:08:49 -04001257 }
Dees_Troyab10ee22012-09-21 14:27:30 -04001258#ifdef SP1_NAME
1259 if ((*iter)->Backup_Name == EXPAND(SP1_NAME)) {
1260 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1261 DataManager::SetValue(TW_BACKUP_SP1_SIZE, backup_display_size);
1262 }
1263#endif
1264#ifdef SP2_NAME
1265 if ((*iter)->Backup_Name == EXPAND(SP2_NAME)) {
1266 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1267 DataManager::SetValue(TW_BACKUP_SP2_SIZE, backup_display_size);
1268 }
1269#endif
1270#ifdef SP3_NAME
1271 if ((*iter)->Backup_Name == EXPAND(SP3_NAME)) {
1272 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1273 DataManager::SetValue(TW_BACKUP_SP3_SIZE, backup_display_size);
1274 }
1275#endif
Dees_Troyaa9cc402012-10-13 12:14:05 -04001276 } else {
1277 // Handle unmountable partitions in case we reset defaults
1278 if ((*iter)->Mount_Point == "/boot") {
1279 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1280 DataManager::SetValue(TW_BACKUP_BOOT_SIZE, backup_display_size);
1281 if ((*iter)->Backup_Size == 0) {
1282 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 0);
1283 DataManager::SetValue(TW_BACKUP_BOOT_VAR, 0);
1284 } else
1285 DataManager::SetValue(TW_HAS_BOOT_PARTITION, 1);
1286 } else if ((*iter)->Mount_Point == "/recovery") {
1287 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1288 DataManager::SetValue(TW_BACKUP_RECOVERY_SIZE, backup_display_size);
1289 if ((*iter)->Backup_Size == 0) {
1290 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 0);
1291 DataManager::SetValue(TW_BACKUP_RECOVERY_VAR, 0);
1292 } else
1293 DataManager::SetValue(TW_HAS_RECOVERY_PARTITION, 1);
Gary Peck82599a82012-11-21 16:23:12 -08001294 } else if ((*iter)->Mount_Point == "/data") {
1295 data_size += (int)((*iter)->Backup_Size / 1048576LLU);
Dees_Troyaa9cc402012-10-13 12:14:05 -04001296 }
1297#ifdef SP1_NAME
1298 if ((*iter)->Backup_Name == EXPAND(SP1_NAME)) {
1299 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1300 DataManager::SetValue(TW_BACKUP_SP1_SIZE, backup_display_size);
1301 }
1302#endif
1303#ifdef SP2_NAME
1304 if ((*iter)->Backup_Name == EXPAND(SP2_NAME)) {
1305 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1306 DataManager::SetValue(TW_BACKUP_SP2_SIZE, backup_display_size);
1307 }
1308#endif
1309#ifdef SP3_NAME
1310 if ((*iter)->Backup_Name == EXPAND(SP3_NAME)) {
1311 int backup_display_size = (int)((*iter)->Backup_Size / 1048576LLU);
1312 DataManager::SetValue(TW_BACKUP_SP3_SIZE, backup_display_size);
1313 }
1314#endif
Dees_Troy51127312012-09-08 13:08:49 -04001315 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001316 }
Dees_Troy51127312012-09-08 13:08:49 -04001317 DataManager::SetValue(TW_BACKUP_DATA_SIZE, data_size);
1318 string current_storage_path = DataManager::GetCurrentStoragePath();
1319 TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
Dees_Troy8170a922012-09-18 15:40:25 -04001320 if (FreeStorage != NULL) {
1321 // Attempt to mount storage
1322 if (!FreeStorage->Mount(false)) {
1323 // We couldn't mount storage... check to see if we have dual storage
1324 int has_dual_storage;
1325 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual_storage);
1326 if (has_dual_storage == 1) {
1327 // We have dual storage, see if we're using the internal storage that should always be present
1328 if (current_storage_path == DataManager::GetSettingsStoragePath()) {
Dees_Troyab10ee22012-09-21 14:27:30 -04001329 if (!FreeStorage->Is_Encrypted) {
1330 // Not able to use internal, so error!
Dees_Troy2673cec2013-04-02 20:22:16 +00001331 LOGERR("Unable to mount internal storage.\n");
Dees_Troyab10ee22012-09-21 14:27:30 -04001332 }
Dees_Troy8170a922012-09-18 15:40:25 -04001333 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1334 } else {
1335 // We were using external, flip to internal
1336 DataManager::SetValue(TW_USE_EXTERNAL_STORAGE, 0);
1337 current_storage_path = DataManager::GetCurrentStoragePath();
1338 FreeStorage = Find_Partition_By_Path(current_storage_path);
1339 if (FreeStorage != NULL) {
1340 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1341 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001342 LOGERR("Unable to locate internal storage partition.\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001343 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1344 }
1345 }
1346 } else {
1347 // No dual storage and unable to mount storage, error!
Dees_Troy2673cec2013-04-02 20:22:16 +00001348 LOGERR("Unable to mount storage.\n");
Dees_Troy8170a922012-09-18 15:40:25 -04001349 DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
1350 }
1351 } else {
1352 DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
1353 }
1354 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001355 LOGINFO("Unable to find storage partition '%s'.\n", current_storage_path.c_str());
Dees_Troy8170a922012-09-18 15:40:25 -04001356 }
Dees_Troy5bf43922012-09-07 16:07:55 -04001357 if (!Write_Fstab())
Dees_Troy2673cec2013-04-02 20:22:16 +00001358 LOGERR("Error creating fstab\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001359 return;
1360}
1361
1362int TWPartitionManager::Decrypt_Device(string Password) {
Dees_Troy5bf43922012-09-07 16:07:55 -04001363#ifdef TW_INCLUDE_CRYPTO
1364 int ret_val, password_len;
1365 char crypto_blkdev[255], cPassword[255];
1366 size_t result;
1367
1368 property_set("ro.crypto.state", "encrypted");
1369#ifdef TW_INCLUDE_JB_CRYPTO
1370 // No extra flags needed
1371#else
1372 property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
1373 property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
1374 property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
1375 property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
1376 property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
1377 property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
a39552696ff55ce2013-01-08 16:14:56 +00001378
1379#ifdef CRYPTO_SD_FS_TYPE
1380 property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
1381 property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
1382 property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
Dees_Troy5bf43922012-09-07 16:07:55 -04001383#endif
a39552696ff55ce2013-01-08 16:14:56 +00001384
1385 property_set("rw.km_fips_status", "ready");
1386
1387#endif
1388
1389 // some samsung devices store "footer" on efs partition
1390 TWPartition *efs = Find_Partition_By_Path("/efs");
1391 if(efs && !efs->Is_Mounted())
1392 efs->Mount(false);
1393 else
1394 efs = 0;
1395#ifdef TW_EXTERNAL_STORAGE_PATH
Dees_Troy20c02c02013-01-10 14:14:10 +00001396#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
a39552696ff55ce2013-01-08 16:14:56 +00001397 TWPartition* sdcard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH));
Dees_Troy85f44ed2013-01-09 18:42:36 +00001398 if (sdcard && sdcard->Mount(false)) {
a39552696ff55ce2013-01-08 16:14:56 +00001399 property_set("ro.crypto.external_encrypted", "1");
1400 property_set("ro.crypto.external_blkdev", sdcard->Actual_Block_Device.c_str());
1401 } else {
1402 property_set("ro.crypto.external_encrypted", "0");
1403 }
1404#endif
Dees_Troy20c02c02013-01-10 14:14:10 +00001405#endif
a39552696ff55ce2013-01-08 16:14:56 +00001406
Dees_Troy5bf43922012-09-07 16:07:55 -04001407 strcpy(cPassword, Password.c_str());
a39552696ff55ce2013-01-08 16:14:56 +00001408 int pwret = cryptfs_check_passwd(cPassword);
1409
1410 if (pwret != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001411 LOGERR("Failed to decrypt data.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001412 return -1;
1413 }
a39552696ff55ce2013-01-08 16:14:56 +00001414
1415 if(efs)
1416 efs->UnMount(false);
1417
Dees_Troy5bf43922012-09-07 16:07:55 -04001418 property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
1419 if (strcmp(crypto_blkdev, "error") == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001420 LOGERR("Error retrieving decrypted data block device.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001421 } else {
1422 TWPartition* dat = Find_Partition_By_Path("/data");
1423 if (dat != NULL) {
Dees_Troy38bd7602012-09-14 13:33:53 -04001424 DataManager::SetValue(TW_DATA_BLK_DEVICE, dat->Primary_Block_Device);
Dees_Troy5bf43922012-09-07 16:07:55 -04001425 DataManager::SetValue(TW_IS_DECRYPTED, 1);
1426 dat->Is_Decrypted = true;
1427 dat->Decrypted_Block_Device = crypto_blkdev;
Gary Peck82599a82012-11-21 16:23:12 -08001428 dat->Setup_File_System(false);
Dees_Troy74fb2e92013-04-15 14:35:47 +00001429 dat->Current_File_System = dat->Fstab_File_System; // Needed if we're ignoring blkid because encrypted devices start out as emmc
Dees_Troy2673cec2013-04-02 20:22:16 +00001430 gui_print("Data successfully decrypted, new block device: '%s'\n", crypto_blkdev);
a39552696ff55ce2013-01-08 16:14:56 +00001431
1432#ifdef CRYPTO_SD_FS_TYPE
1433 char crypto_blkdev_sd[255];
1434 property_get("ro.crypto.sd_fs_crypto_blkdev", crypto_blkdev_sd, "error");
1435 if (strcmp(crypto_blkdev_sd, "error") == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001436 LOGERR("Error retrieving decrypted data block device.\n");
Dees_Troyc8bafa12013-01-10 15:43:00 +00001437 } else if(TWPartition* emmc = Find_Partition_By_Path(EXPAND(TW_INTERNAL_STORAGE_PATH))){
a39552696ff55ce2013-01-08 16:14:56 +00001438 emmc->Is_Decrypted = true;
1439 emmc->Decrypted_Block_Device = crypto_blkdev_sd;
1440 emmc->Setup_File_System(false);
Dees_Troy2673cec2013-04-02 20:22:16 +00001441 gui_print("Internal SD successfully decrypted, new block device: '%s'\n", crypto_blkdev_sd);
a39552696ff55ce2013-01-08 16:14:56 +00001442 }
a39552696ff55ce2013-01-08 16:14:56 +00001443#endif //ifdef CRYPTO_SD_FS_TYPE
Dees_Troy85f44ed2013-01-09 18:42:36 +00001444#ifdef TW_EXTERNAL_STORAGE_PATH
Dees_Troy20c02c02013-01-10 14:14:10 +00001445#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
Dees_Troy85f44ed2013-01-09 18:42:36 +00001446 char is_external_decrypted[255];
1447 property_get("ro.crypto.external_use_ecryptfs", is_external_decrypted, "0");
1448 if (strcmp(is_external_decrypted, "1") == 0) {
1449 sdcard->Is_Decrypted = true;
1450 sdcard->EcryptFS_Password = Password;
1451 sdcard->Decrypted_Block_Device = sdcard->Actual_Block_Device;
Dees_Troy999b39d2013-01-14 15:36:13 +00001452 string MetaEcfsFile = EXPAND(TW_EXTERNAL_STORAGE_PATH);
1453 MetaEcfsFile += "/.MetaEcfsFile";
1454 if (!TWFunc::Path_Exists(MetaEcfsFile)) {
1455 // External storage isn't actually encrypted so unmount and remount without ecryptfs
1456 sdcard->UnMount(false);
1457 sdcard->Mount(false);
1458 }
Dees_Troy85f44ed2013-01-09 18:42:36 +00001459 } else {
Dees_Troy066eb302013-08-23 17:20:32 +00001460 LOGINFO("External storage '%s' is not encrypted.\n", sdcard->Mount_Point.c_str());
Dees_Troy85f44ed2013-01-09 18:42:36 +00001461 sdcard->Is_Decrypted = false;
1462 sdcard->Decrypted_Block_Device = "";
1463 }
Dees_Troy20c02c02013-01-10 14:14:10 +00001464#endif
Dees_Troy85f44ed2013-01-09 18:42:36 +00001465#endif //ifdef TW_EXTERNAL_STORAGE_PATH
a39552696ff55ce2013-01-08 16:14:56 +00001466
Dees_Troy5bf43922012-09-07 16:07:55 -04001467 // Sleep for a bit so that the device will be ready
1468 sleep(1);
Dees_Troy16b74352012-11-14 22:27:31 +00001469#ifdef RECOVERY_SDCARD_ON_DATA
1470 if (dat->Mount(false) && TWFunc::Path_Exists("/data/media/0")) {
1471 dat->Storage_Path = "/data/media/0";
1472 dat->Symlink_Path = dat->Storage_Path;
Dees Troy98fb46c2013-12-04 16:56:45 +00001473 DataManager::SetValue("tw_storage_path", "/data/media/0");
Dees_Troy16b74352012-11-14 22:27:31 +00001474 dat->UnMount(false);
Dees_Troydc8bc1b2013-01-17 01:39:28 +00001475 Output_Partition(dat);
Dees_Troy16b74352012-11-14 22:27:31 +00001476 }
1477#endif
Dees_Troy5bf43922012-09-07 16:07:55 -04001478 Update_System_Details();
Dees_Troyd0384ef2012-10-12 12:15:42 -04001479 UnMount_Main_Partitions();
Dees_Troy5bf43922012-09-07 16:07:55 -04001480 } else
Dees_Troy2673cec2013-04-02 20:22:16 +00001481 LOGERR("Unable to locate data partition.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001482 }
1483 return 0;
1484#else
Dees_Troy2673cec2013-04-02 20:22:16 +00001485 LOGERR("No crypto support was compiled into this build.\n");
Dees_Troy5bf43922012-09-07 16:07:55 -04001486 return -1;
1487#endif
Dees_Troy51a0e822012-09-05 15:24:24 -04001488 return 1;
Dees_Troy51127312012-09-08 13:08:49 -04001489}
1490
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001491int TWPartitionManager::Fix_Permissions(void) {
1492 int result = 0;
1493 if (!Mount_By_Path("/data", true))
1494 return false;
1495
1496 if (!Mount_By_Path("/system", true))
1497 return false;
1498
1499 Mount_By_Path("/sd-ext", false);
1500
1501 fixPermissions perms;
1502 result = perms.fixPerms(true, false);
Dees_Troy1a650e62012-10-19 20:54:32 -04001503 UnMount_Main_Partitions();
Dees_Troy2673cec2013-04-02 20:22:16 +00001504 gui_print("Done.\n\n");
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001505 return result;
1506}
1507
Dees_Troyd21618c2012-10-14 18:48:49 -04001508int TWPartitionManager::Open_Lun_File(string Partition_Path, string Lun_File) {
Dees_Troyd21618c2012-10-14 18:48:49 -04001509 TWPartition* Part = Find_Partition_By_Path(Partition_Path);
1510
1511 if (Part == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001512 LOGERR("Unable to locate volume information for USB storage mode.");
Dees_Troyd21618c2012-10-14 18:48:49 -04001513 return false;
1514 }
1515 if (!Part->UnMount(true))
1516 return false;
1517
Dees_Troy2673cec2013-04-02 20:22:16 +00001518 if (TWFunc::write_file(Lun_File, Part->Actual_Block_Device)) {
1519 LOGERR("Unable to write to ums lunfile '%s': (%s)\n", Lun_File.c_str(), strerror(errno));
Dees_Troyd21618c2012-10-14 18:48:49 -04001520 return false;
1521 }
Matt Mowerd9cb9062013-12-14 20:34:45 -06001522 property_set("sys.storage.ums_enabled", "1");
Dees_Troyd21618c2012-10-14 18:48:49 -04001523 return true;
1524}
1525
Dees_Troy8170a922012-09-18 15:40:25 -04001526int TWPartitionManager::usb_storage_enable(void) {
Dees_Troyd21618c2012-10-14 18:48:49 -04001527 int has_dual, has_data_media;
Dees_Troy8170a922012-09-18 15:40:25 -04001528 char lun_file[255];
Dees_Troy8170a922012-09-18 15:40:25 -04001529 string ext_path;
Dees_Troyd21618c2012-10-14 18:48:49 -04001530 bool has_multiple_lun = false;
Dees_Troy8170a922012-09-18 15:40:25 -04001531
1532 DataManager::GetValue(TW_HAS_DUAL_STORAGE, has_dual);
1533 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
1534 if (has_dual == 1 && has_data_media == 0) {
Dees_Troyd21618c2012-10-14 18:48:49 -04001535 string Lun_File_str = CUSTOM_LUN_FILE;
1536 size_t found = Lun_File_str.find("%");
1537 if (found != string::npos) {
1538 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
1539 if (TWFunc::Path_Exists(lun_file))
1540 has_multiple_lun = true;
1541 }
1542 if (!has_multiple_lun) {
Dees_Troyf4ca6122012-10-13 22:17:20 -04001543 // Device doesn't have multiple lun files, mount current storage
Dees_Troyf4ca6122012-10-13 22:17:20 -04001544 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001545 return Open_Lun_File(DataManager::GetCurrentStoragePath(), lun_file);
Dees_Troyf4ca6122012-10-13 22:17:20 -04001546 } else {
1547 // Device has multiple lun files
Dees_Troyf4ca6122012-10-13 22:17:20 -04001548 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001549 if (!Open_Lun_File(DataManager::GetSettingsStoragePath(), lun_file))
Dees_Troyf4ca6122012-10-13 22:17:20 -04001550 return false;
Dees_Troyf4ca6122012-10-13 22:17:20 -04001551 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
Dees_Troyf4ca6122012-10-13 22:17:20 -04001552 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
Dees_Troyd21618c2012-10-14 18:48:49 -04001553 return Open_Lun_File(ext_path, lun_file);
Dees_Troy8170a922012-09-18 15:40:25 -04001554 }
Dees_Troy8170a922012-09-18 15:40:25 -04001555 } else {
1556 if (has_data_media == 0)
1557 ext_path = DataManager::GetCurrentStoragePath();
1558 else
1559 DataManager::GetValue(TW_EXTERNAL_PATH, ext_path);
Dees_Troy8170a922012-09-18 15:40:25 -04001560 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Dees_Troyd21618c2012-10-14 18:48:49 -04001561 return Open_Lun_File(ext_path, lun_file);
Dees_Troy8170a922012-09-18 15:40:25 -04001562 }
1563 return true;
1564}
1565
1566int TWPartitionManager::usb_storage_disable(void) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001567 int index, ret;
1568 char lun_file[255], ch[2] = {0, 0};
1569 string str = ch;
Dees_Troy8170a922012-09-18 15:40:25 -04001570
1571 for (index=0; index<2; index++) {
1572 sprintf(lun_file, CUSTOM_LUN_FILE, index);
Dees_Troy2673cec2013-04-02 20:22:16 +00001573 ret = TWFunc::write_file(lun_file, str);
1574 Mount_All_Storage();
1575 Update_System_Details();
1576 if (ret < 0) {
1577 break;
Dees_Troy8170a922012-09-18 15:40:25 -04001578 }
Dees_Troy8170a922012-09-18 15:40:25 -04001579 }
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();
Matt Mowerd9cb9062013-12-14 20:34:45 -06001583 property_set("sys.storage.ums_enabled", "0");
Dees_Troy2673cec2013-04-02 20:22:16 +00001584 if (ret < 0 && index == 0) {
1585 LOGERR("Unable to write to ums lunfile '%s'.", lun_file);
1586 return false;
1587 } else {
1588 return true;
1589 }
Dees_Troy8170a922012-09-18 15:40:25 -04001590 return true;
Dees_Troy812660f2012-09-20 09:55:17 -04001591}
1592
1593void TWPartitionManager::Mount_All_Storage(void) {
1594 std::vector<TWPartition*>::iterator iter;
1595
1596 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1597 if ((*iter)->Is_Storage)
1598 (*iter)->Mount(false);
1599 }
Dees_Troy2c50e182012-09-26 20:05:28 -04001600}
Dees_Troy9350b8d2012-09-27 12:38:38 -04001601
Dees_Troyd0384ef2012-10-12 12:15:42 -04001602void TWPartitionManager::UnMount_Main_Partitions(void) {
1603 // Unmounts system and data if data is not data/media
1604 // Also unmounts boot if boot is mountable
Dees_Troy2673cec2013-04-02 20:22:16 +00001605 LOGINFO("Unmounting main partitions...\n");
Dees_Troyd0384ef2012-10-12 12:15:42 -04001606
1607 TWPartition* Boot_Partition = Find_Partition_By_Path("/boot");
1608
1609 UnMount_By_Path("/system", true);
1610#ifndef RECOVERY_SDCARD_ON_DATA
1611 UnMount_By_Path("/data", true);
1612#endif
1613 if (Boot_Partition != NULL && Boot_Partition->Can_Be_Mounted)
1614 Boot_Partition->UnMount(true);
1615}
1616
Dees_Troy9350b8d2012-09-27 12:38:38 -04001617int TWPartitionManager::Partition_SDCard(void) {
1618 char mkdir_path[255], temp[255], line[512];
1619 string Command, Device, fat_str, ext_str, swap_str, start_loc, end_loc, ext_format, sd_path, tmpdevice;
1620 int ext, swap, total_size = 0, fat_size;
1621 FILE* fp;
1622
Dees_Troy2673cec2013-04-02 20:22:16 +00001623 gui_print("Partitioning SD Card...\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001624#ifdef TW_EXTERNAL_STORAGE_PATH
1625 TWPartition* SDCard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH));
1626#else
1627 TWPartition* SDCard = Find_Partition_By_Path("/sdcard");
1628#endif
1629 if (SDCard == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001630 LOGERR("Unable to locate device to partition.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001631 return false;
1632 }
1633 if (!SDCard->UnMount(true))
1634 return false;
1635 TWPartition* SDext = Find_Partition_By_Path("/sd-ext");
1636 if (SDext != NULL) {
1637 if (!SDext->UnMount(true))
1638 return false;
1639 }
Vojtech Bocek05534202013-09-11 08:11:56 +02001640
1641 TWFunc::Exec_Cmd("umount \"$SWAPPATH\"");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001642 Device = SDCard->Actual_Block_Device;
1643 // Just use the root block device
1644 Device.resize(strlen("/dev/block/mmcblkX"));
1645
1646 // Find the size of the block device:
1647 fp = fopen("/proc/partitions", "rt");
1648 if (fp == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001649 LOGERR("Unable to open /proc/partitions\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001650 return false;
1651 }
1652
1653 while (fgets(line, sizeof(line), fp) != NULL)
1654 {
1655 unsigned long major, minor, blocks;
1656 char device[512];
1657 char tmpString[64];
1658
1659 if (strlen(line) < 7 || line[0] == 'm') continue;
1660 sscanf(line + 1, "%lu %lu %lu %s", &major, &minor, &blocks, device);
1661
1662 tmpdevice = "/dev/block/";
1663 tmpdevice += device;
1664 if (tmpdevice == Device) {
1665 // Adjust block size to byte size
1666 total_size = (int)(blocks * 1024ULL / 1000000LLU);
1667 break;
1668 }
1669 }
1670 fclose(fp);
1671
1672 DataManager::GetValue("tw_sdext_size", ext);
1673 DataManager::GetValue("tw_swap_size", swap);
1674 DataManager::GetValue("tw_sdpart_file_system", ext_format);
1675 fat_size = total_size - ext - swap;
Dees_Troy2673cec2013-04-02 20:22:16 +00001676 LOGINFO("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);
Dees_Troy9350b8d2012-09-27 12:38:38 -04001677 memset(temp, 0, sizeof(temp));
1678 sprintf(temp, "%i", fat_size);
1679 fat_str = temp;
1680 memset(temp, 0, sizeof(temp));
1681 sprintf(temp, "%i", fat_size + ext);
1682 ext_str = temp;
1683 memset(temp, 0, sizeof(temp));
1684 sprintf(temp, "%i", fat_size + ext + swap);
1685 swap_str = temp;
1686 if (ext + swap > total_size) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001687 LOGERR("EXT + Swap size is larger than sdcard size.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001688 return false;
1689 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001690 gui_print("Removing partition table...\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001691 Command = "parted -s " + Device + " mklabel msdos";
Dees_Troy2673cec2013-04-02 20:22:16 +00001692 LOGINFO("Command is: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001693 if (TWFunc::Exec_Cmd(Command) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001694 LOGERR("Unable to remove partition table.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001695 Update_System_Details();
1696 return false;
1697 }
Dees_Troy2673cec2013-04-02 20:22:16 +00001698 gui_print("Creating FAT32 partition...\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001699 Command = "parted " + Device + " mkpartfs primary fat32 0 " + fat_str + "MB";
Dees_Troy2673cec2013-04-02 20:22:16 +00001700 LOGINFO("Command is: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001701 if (TWFunc::Exec_Cmd(Command) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001702 LOGERR("Unable to create FAT32 partition.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001703 return false;
1704 }
1705 if (ext > 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001706 gui_print("Creating EXT partition...\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001707 Command = "parted " + Device + " mkpartfs primary ext2 " + fat_str + "MB " + ext_str + "MB";
Dees_Troy2673cec2013-04-02 20:22:16 +00001708 LOGINFO("Command is: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001709 if (TWFunc::Exec_Cmd(Command) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001710 LOGERR("Unable to create EXT partition.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001711 Update_System_Details();
1712 return false;
1713 }
1714 }
1715 if (swap > 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001716 gui_print("Creating swap partition...\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001717 Command = "parted " + Device + " mkpartfs primary linux-swap " + ext_str + "MB " + swap_str + "MB";
Dees_Troy2673cec2013-04-02 20:22:16 +00001718 LOGINFO("Command is: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001719 if (TWFunc::Exec_Cmd(Command) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001720 LOGERR("Unable to create swap partition.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001721 Update_System_Details();
1722 return false;
1723 }
1724 }
1725 // recreate TWRP folder and rewrite settings - these will be gone after sdcard is partitioned
1726#ifdef TW_EXTERNAL_STORAGE_PATH
1727 Mount_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1);
1728 DataManager::GetValue(TW_EXTERNAL_PATH, sd_path);
1729 memset(mkdir_path, 0, sizeof(mkdir_path));
1730 sprintf(mkdir_path, "%s/TWRP", sd_path.c_str());
1731#else
1732 Mount_By_Path("/sdcard", 1);
1733 strcpy(mkdir_path, "/sdcard/TWRP");
1734#endif
1735 mkdir(mkdir_path, 0777);
1736 DataManager::Flush();
1737#ifdef TW_EXTERNAL_STORAGE_PATH
1738 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1739 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1740 DataManager::SetValue(TW_ZIP_LOCATION_VAR, EXPAND(TW_EXTERNAL_STORAGE_PATH));
1741#else
1742 DataManager::SetValue(TW_ZIP_EXTERNAL_VAR, "/sdcard");
1743 if (DataManager::GetIntValue(TW_USE_EXTERNAL_STORAGE) == 1)
1744 DataManager::SetValue(TW_ZIP_LOCATION_VAR, "/sdcard");
1745#endif
1746 if (ext > 0) {
1747 if (SDext == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001748 LOGERR("Unable to locate sd-ext partition.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001749 return false;
1750 }
1751 Command = "mke2fs -t " + ext_format + " -m 0 " + SDext->Actual_Block_Device;
Dees_Troy2673cec2013-04-02 20:22:16 +00001752 gui_print("Formatting sd-ext as %s...\n", ext_format.c_str());
1753 LOGINFO("Formatting sd-ext after partitioning, command: '%s'\n", Command.c_str());
Vojtech Bocek05534202013-09-11 08:11:56 +02001754 TWFunc::Exec_Cmd(Command);
Dees_Troy9350b8d2012-09-27 12:38:38 -04001755 }
1756
1757 Update_System_Details();
Dees_Troy2673cec2013-04-02 20:22:16 +00001758 gui_print("Partitioning complete.\n");
Dees_Troy9350b8d2012-09-27 12:38:38 -04001759 return true;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001760}
Dees_Troya13d74f2013-03-24 08:54:55 -05001761
1762void TWPartitionManager::Get_Partition_List(string ListType, std::vector<PartitionList> *Partition_List) {
1763 std::vector<TWPartition*>::iterator iter;
1764 if (ListType == "mount") {
1765 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1766 if ((*iter)->Can_Be_Mounted && !(*iter)->Is_SubPartition) {
1767 struct PartitionList part;
1768 part.Display_Name = (*iter)->Display_Name;
1769 part.Mount_Point = (*iter)->Mount_Point;
1770 part.selected = (*iter)->Is_Mounted();
1771 Partition_List->push_back(part);
1772 }
1773 }
1774 } else if (ListType == "storage") {
1775 char free_space[255];
1776 string Current_Storage = DataManager::GetCurrentStoragePath();
1777 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1778 if ((*iter)->Is_Storage) {
1779 struct PartitionList part;
1780 sprintf(free_space, "%llu", (*iter)->Free / 1024 / 1024);
1781 part.Display_Name = (*iter)->Storage_Name + " (";
1782 part.Display_Name += free_space;
1783 part.Display_Name += "MB)";
1784 part.Mount_Point = (*iter)->Storage_Path;
1785 if ((*iter)->Storage_Path == Current_Storage)
1786 part.selected = 1;
1787 else
1788 part.selected = 0;
1789 Partition_List->push_back(part);
1790 }
1791 }
1792 } else if (ListType == "backup") {
1793 char backup_size[255];
Dees_Troy9e0b71c2013-04-08 13:35:37 +00001794 unsigned long long Backup_Size;
Dees_Troya13d74f2013-03-24 08:54:55 -05001795 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
Dees_Troy9e0b71c2013-04-08 13:35:37 +00001796 if ((*iter)->Can_Be_Backed_Up && !(*iter)->Is_SubPartition && (*iter)->Is_Present) {
Dees_Troya13d74f2013-03-24 08:54:55 -05001797 struct PartitionList part;
Dees_Troy9e0b71c2013-04-08 13:35:37 +00001798 Backup_Size = (*iter)->Backup_Size;
1799 if ((*iter)->Has_SubPartition) {
1800 std::vector<TWPartition*>::iterator subpart;
1801
1802 for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) {
1803 if ((*subpart)->Is_SubPartition && (*subpart)->Can_Be_Backed_Up && (*subpart)->Is_Present && (*subpart)->SubPartition_Of == (*iter)->Mount_Point)
1804 Backup_Size += (*subpart)->Backup_Size;
1805 }
1806 }
1807 sprintf(backup_size, "%llu", Backup_Size / 1024 / 1024);
Dees_Troya13d74f2013-03-24 08:54:55 -05001808 part.Display_Name = (*iter)->Backup_Display_Name + " (";
1809 part.Display_Name += backup_size;
1810 part.Display_Name += "MB)";
1811 part.Mount_Point = (*iter)->Backup_Path;
1812 part.selected = 0;
1813 Partition_List->push_back(part);
1814 }
1815 }
1816 } else if (ListType == "restore") {
1817 string Restore_List, restore_path;
1818 TWPartition* restore_part = NULL;
1819
1820 DataManager::GetValue("tw_restore_list", Restore_List);
1821 if (!Restore_List.empty()) {
1822 size_t start_pos = 0, end_pos = Restore_List.find(";", start_pos);
1823 while (end_pos != string::npos && start_pos < Restore_List.size()) {
1824 restore_path = Restore_List.substr(start_pos, end_pos - start_pos);
Dees_Troy59df9262013-06-19 14:53:57 -05001825 if ((restore_part = Find_Partition_By_Path(restore_path)) != NULL) {
1826 if (restore_part->Backup_Name == "recovery" || restore_part->Is_SubPartition) {
Dees_Troya13d74f2013-03-24 08:54:55 -05001827 // Don't allow restore of recovery (causes problems on some devices)
Dees_Troy59df9262013-06-19 14:53:57 -05001828 // Don't add subpartitions to the list of items
Dees_Troya13d74f2013-03-24 08:54:55 -05001829 } else {
1830 struct PartitionList part;
1831 part.Display_Name = restore_part->Backup_Display_Name;
1832 part.Mount_Point = restore_part->Backup_Path;
1833 part.selected = 1;
1834 Partition_List->push_back(part);
1835 }
1836 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001837 LOGERR("Unable to locate '%s' partition for restore.\n", restore_path.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -05001838 }
1839 start_pos = end_pos + 1;
1840 end_pos = Restore_List.find(";", start_pos);
1841 }
1842 }
1843 } else if (ListType == "wipe") {
1844 struct PartitionList dalvik;
1845 dalvik.Display_Name = "Dalvik Cache";
1846 dalvik.Mount_Point = "DALVIK";
1847 dalvik.selected = 0;
1848 Partition_List->push_back(dalvik);
1849 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1850 if ((*iter)->Wipe_Available_in_GUI && !(*iter)->Is_SubPartition) {
1851 struct PartitionList part;
1852 part.Display_Name = (*iter)->Display_Name;
1853 part.Mount_Point = (*iter)->Mount_Point;
1854 part.selected = 0;
1855 Partition_List->push_back(part);
1856 }
1857 if ((*iter)->Has_Android_Secure) {
1858 struct PartitionList part;
1859 part.Display_Name = (*iter)->Backup_Display_Name;
1860 part.Mount_Point = (*iter)->Backup_Path;
1861 part.selected = 0;
1862 Partition_List->push_back(part);
1863 }
Dees_Troy74fb2e92013-04-15 14:35:47 +00001864 if ((*iter)->Has_Data_Media) {
1865 struct PartitionList datamedia;
1866 datamedia.Display_Name = (*iter)->Storage_Name;
1867 datamedia.Mount_Point = "INTERNAL";
1868 datamedia.selected = 0;
1869 Partition_List->push_back(datamedia);
1870 }
Dees_Troya13d74f2013-03-24 08:54:55 -05001871 }
1872 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +00001873 LOGERR("Unknown list type '%s' requested for TWPartitionManager::Get_Partition_List\n", ListType.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -05001874 }
1875}
1876
1877int TWPartitionManager::Fstab_Processed(void) {
1878 return Partitions.size();
1879}
Dees_Troyd93bda52013-07-03 19:55:19 +00001880
1881void TWPartitionManager::Output_Storage_Fstab(void) {
1882 std::vector<TWPartition*>::iterator iter;
1883 char storage_partition[255];
1884 string Temp;
1885 FILE *fp = fopen("/cache/recovery/storage.fstab", "w");
1886
1887 if (fp == NULL) {
1888 LOGERR("Unable to open '/cache/recovery/storage.fstab'.\n");
1889 return;
1890 }
1891
1892 // Iterate through all partitions
1893 for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
1894 if ((*iter)->Is_Storage) {
1895 Temp = (*iter)->Storage_Path + ";" + (*iter)->Storage_Name + ";\n";
1896 strcpy(storage_partition, Temp.c_str());
1897 fwrite(storage_partition, sizeof(storage_partition[0]), strlen(storage_partition) / sizeof(storage_partition[0]), fp);
1898 }
1899 }
1900 fclose(fp);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001901}