blob: ef0738232509c9a96dfdd55a84e0475f83b25cbd [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
Ethan Yonker472f5062016-02-25 13:47:30 -06003 Copyright 2013 to 2016 bigbiff/Dees_Troy TeamWin
Dees_Troye34c1332013-02-06 19:13:00 +00004 This file is part of TWRP/TeamWin Recovery Project.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05005
Dees_Troye34c1332013-02-06 19:13:00 +00006 TWRP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050010
Dees_Troye34c1332013-02-06 19:13:00 +000011 TWRP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050015
Dees_Troye34c1332013-02-06 19:13:00 +000016 You should have received a copy of the GNU General Public License
17 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050018*/
19
20extern "C" {
21 #include "libtar/libtar.h"
Dees_Troye34c1332013-02-06 19:13:00 +000022 #include "twrpTar.h"
23 #include "tarWrite.h"
Ethan Yonker4b94cfd2014-12-11 10:00:45 -060024 #include "set_metadata.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050025}
26#include <sys/types.h>
27#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050028#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050029#include <string.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050033#include <iostream>
34#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050035#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000036#include <vector>
bigbiff7abc5fe2015-01-17 16:53:12 -050037#include <csignal>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050038#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040039#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050040#include <sys/mman.h>
bigbiffce8f83c2015-12-12 18:30:21 -050041#include <sys/ioctl.h>
42#include <zlib.h>
43#include <semaphore.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050044#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000045#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050046#include "variables.h"
bigbiffce8f83c2015-12-12 18:30:21 -050047#include "adbbu/libtwadbbu.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050048#include "twrp-functions.hpp"
Ethan Yonker472f5062016-02-25 13:47:30 -060049#include "gui/gui.hpp"
50#include "progresstracking.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050051#ifndef BUILD_TWRPTAR_MAIN
52#include "data.hpp"
53#include "infomanager.hpp"
Ethan Yonker960f0302014-12-21 21:54:00 -060054extern "C" {
55 #include "set_metadata.h"
56}
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050057#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050058
59using namespace std;
60
Dees_Troy83bd4832013-05-04 12:39:56 +000061twrpTar::twrpTar(void) {
62 use_encryption = 0;
63 userdata_encryption = 0;
64 use_compression = 0;
65 split_archives = 0;
66 has_data_media = 0;
67 pigz_pid = 0;
68 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000069 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060070 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000071 include_root_dir = true;
Ethan Yonkerc08b2362016-09-12 16:07:19 -050072 input_fd = -1;
73 output_fd = -1;
Dees_Troy83bd4832013-05-04 12:39:56 +000074}
75
76twrpTar::~twrpTar(void) {
77 // Do nothing
78}
79
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050080void twrpTar::setfn(string fn) {
81 tarfn = fn;
82}
83
84void twrpTar::setdir(string dir) {
85 tardir = dir;
86}
87
Dees Troye0a433a2013-12-02 04:10:37 +000088void twrpTar::setsize(unsigned long long backup_size) {
89 Total_Backup_Size = backup_size;
90}
91
Ethan Yonker87af5632014-02-10 11:56:35 -060092void twrpTar::setpassword(string pass) {
93 password = pass;
94}
95
bigbiff7abc5fe2015-01-17 16:53:12 -050096void twrpTar::Signal_Kill(int signum) {
97 _exit(255);
98}
99
bigbiffce8f83c2015-12-12 18:30:21 -0500100void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
101 current_archive_type = archive_type;
102}
103
104int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000105 int status = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500106 pid_t rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500107 int progress_pipe[2], ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500108 char cmd[512];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500109
110 file_count = 0;
111
bigbiffce8f83c2015-12-12 18:30:21 -0500112 if (part_settings->adbbackup) {
113 std::string Backup_FileName(tarfn);
114 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
115 return -1;
116 }
117
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500118 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500119 LOGINFO("Error creating progress tracking pipe\n");
120 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500121 return -1;
122 }
bigbiffce8f83c2015-12-12 18:30:21 -0500123 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000124 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500125 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500126 close(progress_pipe[0]);
127 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500128 return -1;
129 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500130
bigbiffce8f83c2015-12-12 18:30:21 -0500131 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500132 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500133 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500134 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500135 close(progress_pipe[0]);
136 progress_pipe_fd = progress_pipe[1];
137
Dees_Troy83bd4832013-05-04 12:39:56 +0000138 if (use_encryption || userdata_encryption) {
139 LOGINFO("Using encryption\n");
140 DIR* d;
141 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200142 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
143 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000144 int item_len, ret, thread_error = 0;
145 std::vector<TarListStruct> RegularList;
146 std::vector<TarListStruct> EncryptList;
147 string FileName;
148 struct TarListStruct TarItem;
149 twrpTar reg, enc[9];
150 struct stat st;
151 pthread_t enc_thread[9];
152 pthread_attr_t tattr;
153 void *thread_return;
154
155 core_count = sysconf(_SC_NPROCESSORS_CONF);
156 if (core_count > 8)
157 core_count = 8;
that2252d242015-04-03 22:33:04 +0200158 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000159 Archive_Current_Size = 0;
160
161 d = opendir(tardir.c_str());
162 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500163 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500164 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000165 _exit(-1);
166 }
167 // Figure out the size of all data to be encrypted and create a list of unencrypted files
168 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500169 FileName = tardir + "/" + de->d_name;
170
171 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000172 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500173 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000174 item_len = strlen(de->d_name);
175 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500176 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
177 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500178 LOGINFO("Error in Generate_TarList with regular list!\n");
179 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000180 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500181 close(progress_pipe_fd);
182 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000183 _exit(-1);
184 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500185 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500186 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000187 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500188 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000189 }
190 } else if (de->d_type == DT_REG) {
191 stat(FileName.c_str(), &st);
192 encrypt_size += (unsigned long long)(st.st_size);
193 }
194 }
195 closedir(d);
196
197 target_size = encrypt_size / core_count;
198 target_size++;
199 LOGINFO(" Unencrypted size: %llu\n", regular_size);
200 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
201 LOGINFO(" Target size : %llu\n", target_size);
202 if (!userdata_encryption) {
203 enc_thread_id = 0;
204 start_thread_id = 0;
205 core_count--;
206 }
207 Archive_Current_Size = 0;
208
209 d = opendir(tardir.c_str());
210 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500211 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500212 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000213 _exit(-1);
214 }
215 // Divide up the encrypted file list for threading
216 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500217 FileName = tardir + "/" + de->d_name;
218
219 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000220 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500221 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000222 item_len = strlen(de->d_name);
223 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
224 // Do nothing, we added these to RegularList earlier
225 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500226 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500227 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
228 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500229 LOGINFO("Error in Generate_TarList with encrypted list!\n");
230 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000231 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500232 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000233 _exit(-1);
234 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500235 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000236 }
237 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
238 stat(FileName.c_str(), &st);
239 if (de->d_type == DT_REG)
240 Archive_Current_Size += (unsigned long long)(st.st_size);
241 TarItem.fn = FileName;
242 TarItem.thread_id = enc_thread_id;
243 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500244 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000245 }
246 }
247 closedir(d);
248 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500249 LOGINFO("Error dividing up threads for encryption, %u threads for %u cores!\n", enc_thread_id, core_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500250 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500251 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500252 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000253 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500254 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500255 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500256 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000257 }
258
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500259 // Send file count to parent
260 write(progress_pipe_fd, &file_count, sizeof(file_count));
261 // Send backup size to parent
262 total_size = regular_size + encrypt_size;
263 write(progress_pipe_fd, &total_size, sizeof(total_size));
264
Dees_Troy83bd4832013-05-04 12:39:56 +0000265 if (userdata_encryption) {
266 // Create a backup of unencrypted data
267 reg.setfn(tarfn);
268 reg.ItemList = &RegularList;
269 reg.thread_id = 0;
270 reg.use_encryption = 0;
271 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000272 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500273 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500274 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000275 LOGINFO("Creating unencrypted backup...\n");
276 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500277 LOGINFO("Error creating unencrypted backup.\n");
278 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500279 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000280 _exit(-1);
281 }
282 }
283
284 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500285 LOGINFO("Unable to pthread_attr_init\n");
286 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500287 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000288 _exit(-1);
289 }
290 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500291 LOGINFO("Error setting pthread_attr_setdetachstate\n");
292 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500293 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000294 _exit(-1);
295 }
296 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500297 LOGINFO("Error setting pthread_attr_setscope\n");
298 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500299 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000300 _exit(-1);
301 }
302 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
303 LOGERR("Error setting pthread_attr_setstacksize\n");
304 _exit(-1);
305 }*/
306
307 // Create threads for the divided up encryption lists
308 for (i = start_thread_id; i <= core_count; i++) {
309 enc[i].setdir(tardir);
310 enc[i].setfn(tarfn);
311 enc[i].ItemList = &EncryptList;
312 enc[i].thread_id = i;
313 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500314 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000315 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000316 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500317 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500318 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 LOGINFO("Start encryption thread %i\n", i);
320 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
321 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500322 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).\n", i, ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000323 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500324 LOGINFO("Error creating encrypted backup %i.\n", i);
325 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500326 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000327 _exit(-1);
328 } else {
329 enc[i].thread_id = i + 1;
330 }
331 }
332 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
333 }
334 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500335 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000336 }
337 for (i = start_thread_id; i <= core_count; i++) {
338 if (enc[i].thread_id == i) {
339 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500340 LOGINFO("Error joining thread %i\n", i);
341 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500342 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000343 _exit(-1);
344 } else {
345 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200346 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000347 if (ret != 0) {
348 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500349 LOGINFO("Thread %i returned an error %i.\n", i, ret);
350 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500351 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000352 _exit(-1);
353 }
354 }
355 } else {
356 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
357 }
358 }
359 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500360 LOGINFO("Error returned by one or more threads.\n");
361 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500362 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000363 _exit(-1);
364 }
365 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500366 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000367 _exit(0);
368 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500369 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000370 std::vector<TarListStruct> FileList;
371 unsigned thread_id = 0;
372 unsigned long long target_size = 0;
373 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500374 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000375
376 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500377 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
378 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500379 LOGINFO("Error in Generate_TarList!\n");
380 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500381 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000382 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000383 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500384 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000385 // Create a backup
386 reg.setfn(tarfn);
387 reg.ItemList = &FileList;
388 reg.thread_id = 0;
389 reg.use_encryption = 0;
390 reg.use_compression = use_compression;
391 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500392 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500393 reg.part_settings = part_settings;
394 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500395 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000396 reg.split_archives = 1;
397 } else {
398 reg.split_archives = 0;
399 }
400 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500401 write(progress_pipe_fd, &file_count, sizeof(file_count));
402 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000403 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500404 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500405 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000406 _exit(-1);
407 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500408 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000409 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000410 }
411 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500412 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600413 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500414 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500415
416 // Parent closes output side
417 close(progress_pipe[1]);
418
419 // Read progress data from children
420 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
421 if (first_data == 0) {
422 // First incoming data is the file count
423 file_count = fs;
424 if (file_count == 0) file_count = 1; // prevent division by 0 below
425 first_data = 1;
426 } else if (first_data == 1) {
427 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500428 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500429 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500430 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600431 if (fs > 0) {
432 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500433 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600434 } else { // fs == 0 increments the file counter
435 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500436 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600437 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500438 }
439 }
440 close(progress_pipe[0]);
441#ifndef BUILD_TWRPTAR_MAIN
442 DataManager::SetValue("tw_file_progress", "");
443 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500444 part_settings->progress->DisplayFileCount(false);
445 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500446
bigbiffce8f83c2015-12-12 18:30:21 -0500447 if (!part_settings->adbbackup) {
James Christopher Adduonof3c1b2f2016-10-25 00:51:27 -0400448 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500449 backup_info.SetValue("backup_size", size_backup);
450 if (use_compression && use_encryption)
451 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
452 else if (use_encryption)
453 backup_info.SetValue("backup_type", ENCRYPTED);
454 else if (use_compression)
455 backup_info.SetValue("backup_type", COMPRESSED);
456 else
457 backup_info.SetValue("backup_type", UNCOMPRESSED);
458 backup_info.SetValue("file_count", files_backup);
459 backup_info.SaveValues();
460 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500461#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500462 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500463 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500464 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500465 return 0;
466}
467
bigbiffce8f83c2015-12-12 18:30:21 -0500468int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000469 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500470 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500471 int progress_pipe[2], ret;
472
473 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500474 LOGINFO("Error creating progress tracking pipe\n");
475 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500476 return -1;
477 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000478
bigbiff7abc5fe2015-01-17 16:53:12 -0500479 tar_fork_pid = fork();
480 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000481 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500482 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000483 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500484 close(progress_pipe[0]);
485 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500486 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000487 LOGINFO("Single archive\n");
488 if (extract() != 0)
489 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500490 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000491 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500492 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000493 } else {
494 LOGINFO("Multiple archives\n");
495 string temp;
496 char actual_filename[255];
497 twrpTar tars[9];
498 pthread_t tar_thread[9];
499 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500500 unsigned thread_count = 0, i, start_thread_id = 1;
501 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000502 void *thread_return;
503
504 basefn = tarfn;
505 temp = basefn + "%i%02i";
506 tarfn += "000";
507 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500508 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
509 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500510 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000511 _exit(-1);
512 }
513 if (TWFunc::Get_File_Type(tarfn) != 2) {
514 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
515 tars[0].basefn = basefn;
516 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500517 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500518 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000519 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500520 LOGINFO("Error extracting split archive.\n");
521 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500522 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000523 _exit(-1);
524 }
525 } else {
526 start_thread_id = 0;
527 }
528 // Start threading encrypted restores
529 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500530 LOGINFO("Unable to pthread_attr_init\n");
531 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500532 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 _exit(-1);
534 }
535 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500536 LOGINFO("Error setting pthread_attr_setdetachstate\n");
537 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500538 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000539 _exit(-1);
540 }
541 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500542 LOGINFO("Error setting pthread_attr_setscope\n");
543 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500544 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000545 _exit(-1);
546 }
547 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
548 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500549 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 _exit(-1);
551 }*/
552 for (i = start_thread_id; i < 9; i++) {
553 sprintf(actual_filename, temp.c_str(), i, 0);
554 if (TWFunc::Path_Exists(actual_filename)) {
555 thread_count++;
556 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500557 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000558 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500559 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500560 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000561 LOGINFO("Creating extract thread ID %i\n", i);
562 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
563 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500564 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).\n", i, ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000565 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500566 LOGINFO("Error extracting backup in thread %i.\n", i);
567 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500568 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000569 _exit(-1);
570 } else {
571 tars[i].thread_id = i + 1;
572 }
573 }
574 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
575 } else {
576 break;
577 }
578 }
579 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
580 if (tars[i].thread_id == i) {
581 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500582 LOGINFO("Error joining thread %i\n", i);
583 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500584 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000585 _exit(-1);
586 } else {
587 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200588 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000589 if (ret != 0) {
590 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500591 LOGINFO("Thread %i returned an error %i.\n", i, ret);
592 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500593 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000594 _exit(-1);
595 }
596 }
597 } else {
598 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
599 }
600 }
601 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500602 LOGINFO("Error returned by one or more threads.\n");
603 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500604 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000605 _exit(-1);
606 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500607 LOGINFO("Finished encrypted restore.\n");
608 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000609 _exit(0);
610 }
611 }
612 else // parent process
613 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600614 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500615
616 // Parent closes output side
617 close(progress_pipe[1]);
618
619 // Read progress data from children
620 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
621 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500622 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500623 }
624 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500625 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500626
bigbiff7abc5fe2015-01-17 16:53:12 -0500627 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000628 return -1;
629 }
630 }
631 else // fork has failed
632 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500633 close(progress_pipe[0]);
634 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000635 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500636 return -1;
637 }
638 return 0;
639}
640
Dees_Troy83bd4832013-05-04 12:39:56 +0000641int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
642 DIR* d;
643 struct dirent* de;
644 struct stat st;
645 string FileName;
646 struct TarListStruct TarItem;
647 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500648 int ret, file_count;
649 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000650
Dees_Troy83bd4832013-05-04 12:39:56 +0000651 d = opendir(Path.c_str());
652 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500653 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000654 closedir(d);
655 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500656 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000657 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500658 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500659
Matt Mower50248ab2014-03-31 15:58:40 -0500660 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000661 continue;
662 TarItem.fn = FileName;
663 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500664 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000665 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500666 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
667 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500668 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500669 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000670 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
671 stat(FileName.c_str(), &st);
672 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500673 if (de->d_type == DT_REG) {
674 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000675 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500676 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000677 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
678 *thread_id = *thread_id + 1;
679 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500680 }
681 }
682 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000683 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500684 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500685}
686
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500687int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000688 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000689 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500690 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500691 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500692 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
693 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500694 return -1;
695 }
696 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500697 LOGINFO("Unable to close tar file\n");
698 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500699 return -1;
700 }
bigbiffce8f83c2015-12-12 18:30:21 -0500701 if (part_settings->adbbackup) {
702 if (!twadbbu::Write_TWEOF())
703 return -1;
704 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500705 return 0;
706}
707
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500708int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500709 if (!part_settings->adbbackup) {
710 LOGINFO("Setting archive type\n");
711 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
712 }
713 else {
714 if (part_settings->adb_compression == 1)
715 current_archive_type = COMPRESSED;
716 else
717 current_archive_type = UNCOMPRESSED;
718 }
n0d33b511632013-03-06 21:14:15 +0200719
bigbiffce8f83c2015-12-12 18:30:21 -0500720 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500721 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000722 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000723 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500724 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500725 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600726 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000727 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500728 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000729 return -1;
730 }
731 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500732 LOGINFO("Decrypted file is not in tar format.\n");
733 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000734 return -1;
735 }
736 if (ret == 3) {
737 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500738 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000739 } else
740 LOGINFO("Extracting encrypted tar.\n");
741 return extractTar();
742 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000743 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500744 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500745 }
746}
747
Dees Troye0a433a2013-12-02 04:10:37 +0000748int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000749 struct stat st;
750 char buf[PATH_MAX];
751 int list_size = TarList->size(), i = 0, archive_count = 0;
752 string temp;
753 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000754 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500755 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000756
Dees Troye0a433a2013-12-02 04:10:37 +0000757 if (split_archives) {
758 basefn = tarfn;
759 temp = basefn + "%i%02i";
760 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
761 tarfn = actual_filename;
762 include_root_dir = true;
763 } else {
764 include_root_dir = false;
765 }
bigbiffce8f83c2015-12-12 18:30:21 -0500766
767 if (part_settings->adbbackup)
768 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
769 else
770 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
771
Dees_Troy83bd4832013-05-04 12:39:56 +0000772 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500773 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
774 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000775 return -2;
776 }
777 Archive_Current_Size = 0;
778
779 while (i < list_size) {
780 if (TarList->at(i).thread_id == thread_id) {
781 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400782 lstat(buf, &st);
783 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500784 fs = (unsigned long long)(st.st_size);
785 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000786 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500787 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
788 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000789 return -3;
790 }
791 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500792 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000793 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500794 LOGINFO("Too many archives for thread %i\n", thread_id);
795 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000796 return -4;
797 }
798 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
799 tarfn = actual_filename;
800 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500801 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
802 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000803 return -2;
804 }
805 Archive_Current_Size = 0;
806 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500807 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600808 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500809 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000810 }
Dees Troye0a433a2013-12-02 04:10:37 +0000811 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
812 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500813 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
814 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000815 return -1;
816 }
817 }
818 i++;
819 }
820 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500821 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
822 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000823 return -3;
824 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600825 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000826 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500827}
828
Dees_Troy83bd4832013-05-04 12:39:56 +0000829void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600831 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000832 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
833 return (void*)-2;
834 }
835 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
836 return (void*)0;
837}
838
839void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000840 twrpTar* threadTar = (twrpTar*) cookie;
841 int archive_count = 0;
842 string temp = threadTar->basefn + "%i%02i";
843 char actual_filename[255];
844 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
845 while (TWFunc::Path_Exists(actual_filename)) {
846 threadTar->tarfn = actual_filename;
847 if (threadTar->extract() != 0) {
848 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
849 return (void*)-2;
850 }
851 archive_count++;
852 if (archive_count > 99)
853 break;
854 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
855 }
856 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
857 return (void*)0;
858}
859
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500860int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
861 char* charTarFile = (char*) fn.c_str();
862
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200863 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500864 return -1;
865 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200866 if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500867 return -1;
868 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500869 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500870 if (tar_append_file(t, file, file) == -1)
871 return -1;
872 }
873 if (tar_append_eof(t) == -1)
874 return -1;
875 if (tar_close(t) == -1)
876 return -1;
877 return 0;
878}
879
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500880int twrpTar::createTar() {
881 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000882 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500883
Dees_Troy83bd4832013-05-04 12:39:56 +0000884 if (use_encryption && use_compression) {
885 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500886 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000887 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000888 int i, pipes[4];
889
890 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500891 LOGINFO("Error creating first pipe\n");
892 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500893 return -1;
894 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000895 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500896 LOGINFO("Error creating second pipe\n");
897 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500898 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000899 }
bigbiffce8f83c2015-12-12 18:30:21 -0500900 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
Dees Troy9d723272014-04-07 17:13:10 +0000901 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500902 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000903 for (i = 0; i < 4; i++)
904 close(pipes[i]); // close all
905 return -1;
906 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000907 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400908
Dees_Troy83bd4832013-05-04 12:39:56 +0000909 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500910 LOGINFO("pigz fork() failed\n");
911 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000912 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000913 for (i = 0; i < 4; i++)
914 close(pipes[i]); // close all
915 return -1;
916 } else if (pigz_pid == 0) {
917 // pigz Child
918 close(pipes[1]);
919 close(pipes[2]);
Ethan Yonkerc08b2362016-09-12 16:07:19 -0500920 int stdinfd = fileno(stdin);
921 int stdoutfd = fileno(stdout);
922 close(stdinfd);
923 dup2(pipes[0], stdinfd);
924 close(stdoutfd);
925 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000926 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500927 LOGINFO("execlp pigz ERROR!\n");
928 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000929 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000930 close(pipes[0]);
931 close(pipes[3]);
932 _exit(-1);
933 }
934 } else {
935 // Parent
936 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400937
Dees_Troy83bd4832013-05-04 12:39:56 +0000938 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500939 LOGINFO("openaes fork() failed\n");
940 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000941 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000942 for (i = 0; i < 4; i++)
943 close(pipes[i]); // close all
944 return -1;
945 } else if (oaes_pid == 0) {
946 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000947 close(pipes[0]);
948 close(pipes[1]);
949 close(pipes[3]);
Ethan Yonkerc08b2362016-09-12 16:07:19 -0500950 int stdinfd = fileno(stdin);
951 int stdoutfd = fileno(stdout);
952 close(stdinfd);
953 dup2(pipes[2], stdinfd);
954 close(stdoutfd);
955 dup2(output_fd, stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -0600956 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500957 LOGINFO("execlp openaes ERROR!\n");
958 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000959 close(pipes[2]);
960 close(output_fd);
961 _exit(-1);
962 }
963 } else {
964 // Parent
965 close(pipes[0]);
966 close(pipes[2]);
967 close(pipes[3]);
968 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600969 init_libtar_no_buffer(progress_pipe_fd);
970 tar_type = { open, close, read, write_tar_no_buffer };
971 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000972 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500973 LOGINFO("tar_fdopen failed\n");
974 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000975 return -1;
976 }
977 return 0;
978 }
979 }
980 } else if (use_compression) {
981 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500982 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000983 LOGINFO("Using compression...\n");
984 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500985 if (part_settings->adbbackup) {
986 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
987 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
988 }
989 else {
990 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
991 }
Dees Troy9d723272014-04-07 17:13:10 +0000992 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500993 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000994 close(pigzfd[0]);
995 return -1;
996 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000997
998 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500999 LOGINFO("Error creating pipe\n");
1000 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001001 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001002 return -1;
1003 }
1004 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001005
Dees_Troy83bd4832013-05-04 12:39:56 +00001006 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001007 LOGINFO("fork() failed\n");
1008 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001009 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001010 close(pigzfd[0]);
1011 close(pigzfd[1]);
1012 return -1;
1013 } else if (pigz_pid == 0) {
1014 // Child
1015 close(pigzfd[1]); // close unused output pipe
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001016 dup2(pigzfd[0], fileno(stdin)); // remap stdin
1017 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001018 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001019 LOGINFO("execlp pigz ERROR!\n");
1020 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001021 close(output_fd);
1022 close(pigzfd[0]);
1023 _exit(-1);
1024 }
1025 } else {
1026 // Parent
1027 close(pigzfd[0]); // close parent input
1028 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001029 init_libtar_no_buffer(progress_pipe_fd);
1030 tar_type = { open, close, read, write_tar_no_buffer };
1031 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001032 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001033 LOGINFO("tar_fdopen failed\n");
1034 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001035 return -1;
1036 }
1037 }
1038 } else if (use_encryption) {
1039 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001040 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001041 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001042 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001043 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
Dees Troy9d723272014-04-07 17:13:10 +00001044 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001045 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001046 return -1;
1047 }
1048 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001049 LOGINFO("Error creating pipe\n");
1050 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001051 close(output_fd);
1052 return -1;
1053 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001055
Dees_Troy83bd4832013-05-04 12:39:56 +00001056 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001057 LOGINFO("fork() failed\n");
1058 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001059 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001060 close(oaesfd[0]);
1061 close(oaesfd[1]);
1062 return -1;
1063 } else if (oaes_pid == 0) {
1064 // Child
1065 close(oaesfd[1]); // close unused
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001066 dup2(oaesfd[0], fileno(stdin)); // remap stdin
1067 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001068 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001069 LOGINFO("execlp openaes ERROR!\n");
1070 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001071 close(output_fd);
1072 close(oaesfd[0]);
1073 _exit(-1);
1074 }
1075 } else {
1076 // Parent
1077 close(oaesfd[0]); // close parent input
1078 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001079 init_libtar_no_buffer(progress_pipe_fd);
1080 tar_type = { open, close, read, write_tar_no_buffer };
1081 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001082 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001083 LOGINFO("tar_fdopen failed\n");
1084 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001085 return -1;
1086 }
1087 return 0;
1088 }
1089 } else {
1090 // Not compressed or encrypted
Ethan Yonker472f5062016-02-25 13:47:30 -06001091 init_libtar_buffer(0, progress_pipe_fd);
1092 tar_type = { open, close, read, write_tar };
bigbiffce8f83c2015-12-12 18:30:21 -05001093 if (part_settings->adbbackup) {
1094 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
1095 tar_type = { open, close, read, write_tar_no_buffer };
1096 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1097 if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
1098 close(output_fd);
1099 LOGERR("tar_fdopen failed\n");
1100 return -1;
1101 }
1102 }
1103 else {
1104 if (tar_open(&t, charTarFile, &tar_type, O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1) {
1105 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1106 gui_err("backup_error=Error creating backup.");
1107 return -1;
1108 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001109 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001110 }
1111 return 0;
1112}
1113
Dees_Troy83bd4832013-05-04 12:39:56 +00001114int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001115 char* charRootDir = (char*) tardir.c_str();
1116 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001117 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001118
bigbiffce8f83c2015-12-12 18:30:21 -05001119 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001120 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001121 int i, pipes[4];
bigbiffce8f83c2015-12-12 18:30:21 -05001122 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001123 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001124 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001125 return -1;
1126 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001127
1128 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001129 LOGINFO("Error creating first pipe\n");
1130 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001131 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001132 return -1;
1133 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001134 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001135 LOGINFO("Error creating second pipe\n");
1136 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001137 close(pipes[0]);
1138 close(pipes[1]);
1139 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001140 return -1;
1141 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001142 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001143
Dees_Troy83bd4832013-05-04 12:39:56 +00001144 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001145 LOGINFO("pigz fork() failed\n");
1146 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001147 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001148 for (i = 0; i < 4; i++)
1149 close(pipes[i]); // close all
1150 return -1;
1151 } else if (oaes_pid == 0) {
1152 // openaes Child
1153 close(pipes[0]); // Close pipes that are not used by this child
1154 close(pipes[2]);
1155 close(pipes[3]);
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001156 int stdinfd = fileno(stdin);
1157 int stdoutfd = fileno(stdout);
1158 close(stdinfd);
1159 dup2(input_fd, stdinfd);
1160 close(stdoutfd);
1161 dup2(pipes[1], stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -06001162 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001163 LOGINFO("execlp openaes ERROR!\n");
1164 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001165 close(input_fd);
1166 close(pipes[1]);
1167 _exit(-1);
1168 }
1169 } else {
1170 // Parent
1171 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001172
Dees_Troy83bd4832013-05-04 12:39:56 +00001173 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001174 LOGINFO("openaes fork() failed\n");
1175 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001176 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001177 for (i = 0; i < 4; i++)
1178 close(pipes[i]); // close all
1179 return -1;
1180 } else if (pigz_pid == 0) {
1181 // pigz Child
1182 close(pipes[1]); // Close pipes not used by this child
1183 close(pipes[2]);
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001184 int stdinfd = fileno(stdin);
1185 int stdoutfd = fileno(stdout);
1186 close(stdinfd);
1187 dup2(pipes[0], stdinfd);
1188 close(stdoutfd);
1189 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001190 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001191 LOGINFO("execlp pigz ERROR!\n");
1192 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001193 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001194 close(pipes[0]);
1195 close(pipes[3]);
1196 _exit(-1);
1197 }
1198 } else {
1199 // Parent
1200 close(pipes[0]); // Close pipes not used by parent
1201 close(pipes[1]);
1202 close(pipes[3]);
1203 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001204 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001205 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001206 LOGINFO("tar_fdopen failed\n");
1207 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001208 return -1;
1209 }
1210 }
1211 }
bigbiffce8f83c2015-12-12 18:30:21 -05001212 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001213 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001214 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001215 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001216 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001217 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001218 return -1;
1219 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001220
Dees Troy9d723272014-04-07 17:13:10 +00001221 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001222 LOGINFO("Error creating pipe\n");
1223 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001224 close(input_fd);
1225 return -1;
1226 }
1227
Dees_Troy83bd4832013-05-04 12:39:56 +00001228 oaes_pid = fork();
1229 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001230 LOGINFO("fork() failed\n");
1231 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001232 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001233 close(oaesfd[0]);
1234 close(oaesfd[1]);
1235 return -1;
1236 } else if (oaes_pid == 0) {
1237 // Child
1238 close(oaesfd[0]); // Close unused pipe
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001239 int stdinfd = fileno(stdin);
1240 close(stdinfd); // close stdin
1241 dup2(oaesfd[1], fileno(stdout)); // remap stdout
1242 dup2(input_fd, stdinfd); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001243 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001244 LOGINFO("execlp openaes ERROR!\n");
1245 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001246 close(input_fd);
1247 close(oaesfd[1]);
1248 _exit(-1);
1249 }
1250 } else {
1251 // Parent
1252 close(oaesfd[1]); // close parent output
1253 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001254 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001255 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001256 LOGINFO("tar_fdopen failed\n");
1257 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001258 return -1;
1259 }
1260 }
bigbiffce8f83c2015-12-12 18:30:21 -05001261 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001262 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001263
1264 LOGINFO("Opening as a gzip...\n");
1265 if (part_settings->adbbackup) {
1266 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
1267 input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE);
1268 }
1269 else
1270 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1271
Dees Troy9d723272014-04-07 17:13:10 +00001272 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001273 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001274 return -1;
1275 }
bigbiffce8f83c2015-12-12 18:30:21 -05001276
Dees Troy9d723272014-04-07 17:13:10 +00001277 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001278 LOGINFO("Error creating pipe\n");
1279 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001280 close(input_fd);
1281 return -1;
1282 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001283
1284 pigz_pid = fork();
1285 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001286 LOGINFO("fork() failed\n");
1287 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001288 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001289 close(pigzfd[0]);
1290 close(pigzfd[1]);
1291 return -1;
1292 } else if (pigz_pid == 0) {
1293 // Child
1294 close(pigzfd[0]);
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001295 dup2(pigzfd[1], fileno(stdout)); // remap stdout
1296 dup2(input_fd, fileno(stdin)); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001297 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1298 close(pigzfd[1]);
1299 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001300 LOGINFO("execlp openaes ERROR!\n");
1301 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001302 _exit(-1);
1303 }
1304 } else {
1305 // Parent
1306 close(pigzfd[1]); // close parent output
1307 fd = pigzfd[0]; // copy parent input
bigbiffce8f83c2015-12-12 18:30:21 -05001308 if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001309 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001310 LOGINFO("tar_fdopen failed\n");
1311 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001312 return -1;
1313 }
1314 }
bigbiffce8f83c2015-12-12 18:30:21 -05001315 } else {
1316 if (part_settings->adbbackup) {
1317 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1318 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
1319 if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
1320 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1321 gui_err("restore_error=Error during restore process.");
1322 return -1;
1323 }
1324 }
1325 else {
1326 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
1327 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1328 gui_err("restore_error=Error during restore process.");
1329 return -1;
1330 }
1331 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001332 }
1333 return 0;
1334}
1335
1336string twrpTar::Strip_Root_Dir(string Path) {
1337 string temp;
1338 size_t slash;
1339
1340 if (Path.substr(0, 1) == "/")
1341 temp = Path.substr(1, Path.size() - 1);
1342 else
1343 temp = Path;
1344 slash = temp.find("/");
1345 if (slash == string::npos)
1346 return temp;
1347 else {
1348 string stripped;
1349
1350 stripped = temp.substr(slash, temp.size() - slash);
1351 return stripped;
1352 }
1353 return temp;
1354}
1355
1356int twrpTar::addFile(string fn, bool include_root) {
1357 char* charTarFile = (char*) fn.c_str();
1358 if (include_root) {
1359 if (tar_append_file(t, charTarFile, NULL) == -1)
1360 return -1;
1361 } else {
1362 string temp = Strip_Root_Dir(fn);
1363 char* charTarPath = (char*) temp.c_str();
1364 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1365 return -1;
1366 }
1367 return 0;
1368}
1369
Dees_Troy83bd4832013-05-04 12:39:56 +00001370int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001371 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001372 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001373 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001374 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001375 tar_close(t);
1376 return -1;
1377 }
1378 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001379 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001380 return -1;
1381 }
bigbiffce8f83c2015-12-12 18:30:21 -05001382 if (current_archive_type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001383 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001384 int status;
1385 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1386 return -1;
1387 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1388 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001389 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001390 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001391 if (!part_settings->adbbackup) {
1392 if (use_compression && !use_encryption) {
1393 string gzname = tarfn + ".gz";
1394 if (TWFunc::Path_Exists(gzname)) {
1395 rename(gzname.c_str(), tarfn.c_str());
1396 }
Dees Troye0a433a2013-12-02 04:10:37 +00001397 }
bigbiffce8f83c2015-12-12 18:30:21 -05001398 if (TWFunc::Get_File_Size(tarfn) == 0) {
1399 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1400 return -1;
1401 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001402#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001403 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001404#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001405 }
1406 else {
1407 if (!twadbbu::Write_TWEOF())
1408 return -1;
1409 }
Ethan Yonkerc08b2362016-09-12 16:07:19 -05001410 if (input_fd >= 0)
1411 close(input_fd);
1412 if (output_fd >= 0)
1413 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001414 return 0;
1415}
1416
1417int twrpTar::removeEOT(string tarFile) {
1418 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001419 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001420 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001421 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001422 tar_skip_regfile(t);
1423 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001424 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001425 if (tar_close(t) == -1)
1426 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001427 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001428 return -1;
1429 return 0;
1430}
1431
n0d33b511632013-03-06 21:14:15 +02001432int twrpTar::entryExists(string entry) {
1433 char* searchstr = (char*)entry.c_str();
1434 int ret;
1435
bigbiffce8f83c2015-12-12 18:30:21 -05001436 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001437
Dees_Troy83bd4832013-05-04 12:39:56 +00001438 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001439 ret = 0;
1440 else
1441 ret = tar_find(t, searchstr);
1442
Dees_Troy83bd4832013-05-04 12:39:56 +00001443 if (closeTar() != 0)
1444 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001445
1446 return ret;
1447}
1448
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001449unsigned long long twrpTar::get_size() {
bigbiffce8f83c2015-12-12 18:30:21 -05001450 if (TWFunc::Path_Exists(tarfn) && !part_settings->adbbackup) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001451 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001452 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001453 } else {
1454 LOGINFO("Multiple archives\n");
1455 string temp;
1456 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001457 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001458 unsigned long long total_restore_size = 0;
1459
1460 basefn = tarfn;
1461 temp = basefn + "%i%02i";
1462 tarfn += "000";
1463 thread_id = 0;
1464 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001465 if (!part_settings->adbbackup) {
1466 if (!TWFunc::Path_Exists(actual_filename)) {
1467 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1468 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001469 }
bigbiffce8f83c2015-12-12 18:30:21 -05001470 for (int i = 0; i < 9; i++) {
1471 archive_count = 0;
1472 sprintf(actual_filename, temp.c_str(), i, archive_count);
1473 while (TWFunc::Path_Exists(actual_filename)) {
1474 total_restore_size += uncompressedSize(actual_filename);
1475 archive_count++;
1476 if (archive_count > 99)
1477 break;
1478 sprintf(actual_filename, temp.c_str(), i, archive_count);
1479 }
1480 }
1481 #ifndef BUILD_TWRPTAR_MAIN
1482 if (!part_settings->adbbackup) {
1483 InfoManager backup_info(tarfn + ".info");
1484 backup_info.SetValue("backup_size", total_restore_size);
1485 backup_info.SetValue("backup_type", current_archive_type);
1486 backup_info.SaveValues();
1487 }
1488 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001489 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001490 return total_restore_size;
1491 }
1492 return 0;
1493}
1494
bigbiffce8f83c2015-12-12 18:30:21 -05001495unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001496 unsigned long long total_size = 0;
1497 string Tar, Command, result;
1498 vector<string> split;
1499
bigbiffce8f83c2015-12-12 18:30:21 -05001500 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1501 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001502 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001503 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001504 // Compressed
1505 Command = "pigz -l '" + filename + "'";
1506 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1507 we get the uncompressed size at once. */
1508 TWFunc::Exec_Cmd(Command, result);
1509 if (!result.empty()) {
1510 /* Expected output:
1511 compressed original reduced name
1512 95855838 179403776 -1.3% data.yaffs2.win
1513 ^
1514 split[5]
1515 */
1516 split = TWFunc::split_string(result, ' ', true);
1517 if (split.size() > 4)
1518 total_size = atoi(split[5].c_str());
1519 }
bigbiffce8f83c2015-12-12 18:30:21 -05001520 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001521 // File is encrypted and may be compressed
1522 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001523 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001524 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001525 total_size = TWFunc::Get_File_Size(filename);
1526 } else if (ret == 1) {
1527 LOGERR("Decrypted file is not in tar format.\n");
1528 total_size = TWFunc::Get_File_Size(filename);
1529 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001530 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1531 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1532 we get the uncompressed size at once. */
1533 TWFunc::Exec_Cmd(Command, result);
1534 if (!result.empty()) {
1535 LOGINFO("result was: '%s'\n", result.c_str());
1536 /* Expected output:
1537 compressed original reduced name
1538 95855838 179403776 -1.3% data.yaffs2.win
1539 ^
1540 split[5]
1541 */
1542 split = TWFunc::split_string(result, ' ', true);
1543 if (split.size() > 4)
1544 total_size = atoi(split[5].c_str());
1545 }
1546 } else {
1547 total_size = TWFunc::Get_File_Size(filename);
1548 }
1549 }
1550
1551 return total_size;
1552}
1553
Dees_Troye34c1332013-02-06 19:13:00 +00001554extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1555 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001556}
Ethan Yonker472f5062016-02-25 13:47:30 -06001557
1558extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1559 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1560}