blob: 3c07a97d18ffd3ab5b8225c32bc4cc6203438b08 [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"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050024}
25#include <sys/types.h>
26#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050027#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050028#include <string.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050032#include <iostream>
33#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050034#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000035#include <vector>
bigbiff7abc5fe2015-01-17 16:53:12 -050036#include <csignal>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050037#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040038#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050039#include <sys/mman.h>
bigbiffce8f83c2015-12-12 18:30:21 -050040#include <sys/ioctl.h>
41#include <zlib.h>
42#include <semaphore.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050043#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000044#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050045#include "variables.h"
bigbiffce8f83c2015-12-12 18:30:21 -050046#include "adbbu/libtwadbbu.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050047#include "twrp-functions.hpp"
Ethan Yonker472f5062016-02-25 13:47:30 -060048#include "gui/gui.hpp"
49#include "progresstracking.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050050#ifndef BUILD_TWRPTAR_MAIN
51#include "data.hpp"
52#include "infomanager.hpp"
Ethan Yonkerf1179622016-08-25 15:32:21 -050053#include "set_metadata.h"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050054#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050055
56using namespace std;
57
Dees_Troy83bd4832013-05-04 12:39:56 +000058twrpTar::twrpTar(void) {
59 use_encryption = 0;
60 userdata_encryption = 0;
61 use_compression = 0;
62 split_archives = 0;
63 has_data_media = 0;
64 pigz_pid = 0;
65 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000066 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060067 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000068 include_root_dir = true;
Ethan Yonkerf1179622016-08-25 15:32:21 -050069 tar_type.openfunc = open;
70 tar_type.closefunc = close;
71 tar_type.readfunc = read;
Ethan Yonkerea2fcf02016-09-12 16:07:19 -050072 input_fd = -1;
73 output_fd = -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -060074 backup_exclusions = NULL;
Dees_Troy83bd4832013-05-04 12:39:56 +000075}
76
77twrpTar::~twrpTar(void) {
78 // Do nothing
79}
80
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050081void twrpTar::setfn(string fn) {
82 tarfn = fn;
83}
84
85void twrpTar::setdir(string dir) {
86 tardir = dir;
87}
88
Dees Troye0a433a2013-12-02 04:10:37 +000089void twrpTar::setsize(unsigned long long backup_size) {
90 Total_Backup_Size = backup_size;
91}
92
Ethan Yonker87af5632014-02-10 11:56:35 -060093void twrpTar::setpassword(string pass) {
94 password = pass;
95}
96
bigbiff7abc5fe2015-01-17 16:53:12 -050097void twrpTar::Signal_Kill(int signum) {
98 _exit(255);
99}
100
bigbiffce8f83c2015-12-12 18:30:21 -0500101void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
102 current_archive_type = archive_type;
103}
104
105int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000106 int status = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500107 pid_t rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500108 int progress_pipe[2], ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500109 char cmd[512];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500110
111 file_count = 0;
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600112 if (backup_exclusions == NULL) {
113 LOGINFO("backup_exclusions is NULL\n");
114 return -1;
115 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500116
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600117#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500118 if (part_settings->adbbackup) {
119 std::string Backup_FileName(tarfn);
120 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
121 return -1;
122 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600123#endif
bigbiffce8f83c2015-12-12 18:30:21 -0500124
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500125 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500126 LOGINFO("Error creating progress tracking pipe\n");
127 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500128 return -1;
129 }
bigbiffce8f83c2015-12-12 18:30:21 -0500130 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000131 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500132 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500133 close(progress_pipe[0]);
134 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500135 return -1;
136 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500137
bigbiffce8f83c2015-12-12 18:30:21 -0500138 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500139 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500140 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500141 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500142 close(progress_pipe[0]);
143 progress_pipe_fd = progress_pipe[1];
144
Dees_Troy83bd4832013-05-04 12:39:56 +0000145 if (use_encryption || userdata_encryption) {
146 LOGINFO("Using encryption\n");
147 DIR* d;
148 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200149 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
150 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000151 int item_len, ret, thread_error = 0;
152 std::vector<TarListStruct> RegularList;
153 std::vector<TarListStruct> EncryptList;
154 string FileName;
155 struct TarListStruct TarItem;
156 twrpTar reg, enc[9];
157 struct stat st;
158 pthread_t enc_thread[9];
159 pthread_attr_t tattr;
160 void *thread_return;
161
162 core_count = sysconf(_SC_NPROCESSORS_CONF);
163 if (core_count > 8)
164 core_count = 8;
that2252d242015-04-03 22:33:04 +0200165 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000166 Archive_Current_Size = 0;
167
168 d = opendir(tardir.c_str());
169 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500170 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500171 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000172 _exit(-1);
173 }
174 // Figure out the size of all data to be encrypted and create a list of unencrypted files
175 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500176 FileName = tardir + "/" + de->d_name;
177
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600178 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000179 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500180 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000181 item_len = strlen(de->d_name);
182 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 -0500183 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
184 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500185 LOGINFO("Error in Generate_TarList with regular list!\n");
186 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000187 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500188 close(progress_pipe_fd);
189 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000190 _exit(-1);
191 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500192 file_count = (unsigned long long)(ret);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600193 regular_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000194 } else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600195 encrypt_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000196 }
197 } else if (de->d_type == DT_REG) {
198 stat(FileName.c_str(), &st);
199 encrypt_size += (unsigned long long)(st.st_size);
200 }
201 }
202 closedir(d);
203
204 target_size = encrypt_size / core_count;
205 target_size++;
206 LOGINFO(" Unencrypted size: %llu\n", regular_size);
207 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
208 LOGINFO(" Target size : %llu\n", target_size);
209 if (!userdata_encryption) {
210 enc_thread_id = 0;
211 start_thread_id = 0;
212 core_count--;
213 }
214 Archive_Current_Size = 0;
215
216 d = opendir(tardir.c_str());
217 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500218 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500219 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000220 _exit(-1);
221 }
222 // Divide up the encrypted file list for threading
223 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500224 FileName = tardir + "/" + de->d_name;
225
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600226 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000227 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500228 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000229 item_len = strlen(de->d_name);
230 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
231 // Do nothing, we added these to RegularList earlier
232 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500233 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500234 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
235 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500236 LOGINFO("Error in Generate_TarList with encrypted list!\n");
237 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000238 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500239 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000240 _exit(-1);
241 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 }
244 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
245 stat(FileName.c_str(), &st);
246 if (de->d_type == DT_REG)
247 Archive_Current_Size += (unsigned long long)(st.st_size);
248 TarItem.fn = FileName;
249 TarItem.thread_id = enc_thread_id;
250 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500251 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000252 }
253 }
254 closedir(d);
255 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500256 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 -0500257 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500258 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500259 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000260 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500261 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500262 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500263 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000264 }
265
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500266 // Send file count to parent
267 write(progress_pipe_fd, &file_count, sizeof(file_count));
268 // Send backup size to parent
269 total_size = regular_size + encrypt_size;
270 write(progress_pipe_fd, &total_size, sizeof(total_size));
271
Dees_Troy83bd4832013-05-04 12:39:56 +0000272 if (userdata_encryption) {
273 // Create a backup of unencrypted data
274 reg.setfn(tarfn);
275 reg.ItemList = &RegularList;
276 reg.thread_id = 0;
277 reg.use_encryption = 0;
278 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000279 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500280 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500281 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000282 LOGINFO("Creating unencrypted backup...\n");
283 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500284 LOGINFO("Error creating unencrypted backup.\n");
285 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500286 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000287 _exit(-1);
288 }
289 }
290
291 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500292 LOGINFO("Unable to pthread_attr_init\n");
293 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500294 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000295 _exit(-1);
296 }
297 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500298 LOGINFO("Error setting pthread_attr_setdetachstate\n");
299 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500300 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000301 _exit(-1);
302 }
303 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500304 LOGINFO("Error setting pthread_attr_setscope\n");
305 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500306 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000307 _exit(-1);
308 }
309 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
310 LOGERR("Error setting pthread_attr_setstacksize\n");
311 _exit(-1);
312 }*/
313
314 // Create threads for the divided up encryption lists
315 for (i = start_thread_id; i <= core_count; i++) {
316 enc[i].setdir(tardir);
317 enc[i].setfn(tarfn);
318 enc[i].ItemList = &EncryptList;
319 enc[i].thread_id = i;
320 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500321 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000322 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000323 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500324 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500325 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000326 LOGINFO("Start encryption thread %i\n", i);
327 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
328 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500329 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 +0000330 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500331 LOGINFO("Error creating encrypted backup %i.\n", i);
332 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500333 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000334 _exit(-1);
335 } else {
336 enc[i].thread_id = i + 1;
337 }
338 }
339 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
340 }
341 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500342 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000343 }
344 for (i = start_thread_id; i <= core_count; i++) {
345 if (enc[i].thread_id == i) {
346 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500347 LOGINFO("Error joining thread %i\n", i);
348 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500349 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000350 _exit(-1);
351 } else {
352 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200353 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000354 if (ret != 0) {
355 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500356 LOGINFO("Thread %i returned an error %i.\n", i, ret);
357 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500358 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000359 _exit(-1);
360 }
361 }
362 } else {
363 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
364 }
365 }
366 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500367 LOGINFO("Error returned by one or more threads.\n");
368 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500369 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000370 _exit(-1);
371 }
372 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500373 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000374 _exit(0);
375 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500376 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000377 std::vector<TarListStruct> FileList;
378 unsigned thread_id = 0;
379 unsigned long long target_size = 0;
380 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500381 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000382
383 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500384 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
385 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500386 LOGINFO("Error in Generate_TarList!\n");
387 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500388 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000389 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000390 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500391 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000392 // Create a backup
393 reg.setfn(tarfn);
394 reg.ItemList = &FileList;
395 reg.thread_id = 0;
396 reg.use_encryption = 0;
397 reg.use_compression = use_compression;
398 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500399 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500400 reg.part_settings = part_settings;
401 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500402 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000403 reg.split_archives = 1;
404 } else {
405 reg.split_archives = 0;
406 }
407 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500408 write(progress_pipe_fd, &file_count, sizeof(file_count));
409 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000410 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500411 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500412 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000413 _exit(-1);
414 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500415 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000416 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000417 }
418 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500419 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600420 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500421 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500422
423 // Parent closes output side
424 close(progress_pipe[1]);
425
426 // Read progress data from children
427 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
428 if (first_data == 0) {
429 // First incoming data is the file count
430 file_count = fs;
431 if (file_count == 0) file_count = 1; // prevent division by 0 below
432 first_data = 1;
433 } else if (first_data == 1) {
434 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500435 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500436 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500437 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600438 if (fs > 0) {
439 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500440 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600441 } else { // fs == 0 increments the file counter
442 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500443 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600444 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500445 }
446 }
447 close(progress_pipe[0]);
448#ifndef BUILD_TWRPTAR_MAIN
449 DataManager::SetValue("tw_file_progress", "");
450 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500451 part_settings->progress->DisplayFileCount(false);
452 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500453
bigbiffce8f83c2015-12-12 18:30:21 -0500454 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400455 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500456 backup_info.SetValue("backup_size", size_backup);
457 if (use_compression && use_encryption)
458 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
459 else if (use_encryption)
460 backup_info.SetValue("backup_type", ENCRYPTED);
461 else if (use_compression)
462 backup_info.SetValue("backup_type", COMPRESSED);
463 else
464 backup_info.SetValue("backup_type", UNCOMPRESSED);
465 backup_info.SetValue("file_count", files_backup);
466 backup_info.SaveValues();
467 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500468#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500469 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500470 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500471 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500472 return 0;
473}
474
bigbiffce8f83c2015-12-12 18:30:21 -0500475int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000476 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500477 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500478 int progress_pipe[2], ret;
479
480 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500481 LOGINFO("Error creating progress tracking pipe\n");
482 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500483 return -1;
484 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000485
bigbiff7abc5fe2015-01-17 16:53:12 -0500486 tar_fork_pid = fork();
487 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000488 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500489 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000490 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500491 close(progress_pipe[0]);
492 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500493 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000494 LOGINFO("Single archive\n");
495 if (extract() != 0)
496 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500497 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000498 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500499 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000500 } else {
501 LOGINFO("Multiple archives\n");
502 string temp;
503 char actual_filename[255];
504 twrpTar tars[9];
505 pthread_t tar_thread[9];
506 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500507 unsigned thread_count = 0, i, start_thread_id = 1;
508 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000509 void *thread_return;
510
511 basefn = tarfn;
512 temp = basefn + "%i%02i";
513 tarfn += "000";
514 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500515 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
516 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500517 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000518 _exit(-1);
519 }
520 if (TWFunc::Get_File_Type(tarfn) != 2) {
521 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
522 tars[0].basefn = basefn;
523 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500524 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500525 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000526 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500527 LOGINFO("Error extracting split archive.\n");
528 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500529 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000530 _exit(-1);
531 }
532 } else {
533 start_thread_id = 0;
534 }
535 // Start threading encrypted restores
536 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500537 LOGINFO("Unable to pthread_attr_init\n");
538 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500539 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000540 _exit(-1);
541 }
542 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500543 LOGINFO("Error setting pthread_attr_setdetachstate\n");
544 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500545 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000546 _exit(-1);
547 }
548 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500549 LOGINFO("Error setting pthread_attr_setscope\n");
550 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500551 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000552 _exit(-1);
553 }
554 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
555 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500556 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000557 _exit(-1);
558 }*/
559 for (i = start_thread_id; i < 9; i++) {
560 sprintf(actual_filename, temp.c_str(), i, 0);
561 if (TWFunc::Path_Exists(actual_filename)) {
562 thread_count++;
563 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500564 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000565 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500566 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500567 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000568 LOGINFO("Creating extract thread ID %i\n", i);
569 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
570 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500571 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 +0000572 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500573 LOGINFO("Error extracting backup in thread %i.\n", i);
574 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500575 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000576 _exit(-1);
577 } else {
578 tars[i].thread_id = i + 1;
579 }
580 }
581 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
582 } else {
583 break;
584 }
585 }
586 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
587 if (tars[i].thread_id == i) {
588 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500589 LOGINFO("Error joining thread %i\n", i);
590 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500591 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000592 _exit(-1);
593 } else {
594 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200595 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000596 if (ret != 0) {
597 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500598 LOGINFO("Thread %i returned an error %i.\n", i, ret);
599 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500600 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000601 _exit(-1);
602 }
603 }
604 } else {
605 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
606 }
607 }
608 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500609 LOGINFO("Error returned by one or more threads.\n");
610 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500611 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000612 _exit(-1);
613 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500614 LOGINFO("Finished encrypted restore.\n");
615 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000616 _exit(0);
617 }
618 }
619 else // parent process
620 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600621 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500622
623 // Parent closes output side
624 close(progress_pipe[1]);
625
626 // Read progress data from children
627 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
628 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500629 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500630 }
631 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500632 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500633
bigbiff7abc5fe2015-01-17 16:53:12 -0500634 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000635 return -1;
636 }
637 }
638 else // fork has failed
639 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500640 close(progress_pipe[0]);
641 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000642 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500643 return -1;
644 }
645 return 0;
646}
647
Dees_Troy83bd4832013-05-04 12:39:56 +0000648int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
649 DIR* d;
650 struct dirent* de;
651 struct stat st;
652 string FileName;
653 struct TarListStruct TarItem;
654 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500655 int ret, file_count;
656 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000657
Dees_Troy83bd4832013-05-04 12:39:56 +0000658 d = opendir(Path.c_str());
659 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500660 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000661 closedir(d);
662 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500663 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000664 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500665 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500666
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600667 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000668 continue;
669 TarItem.fn = FileName;
670 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500671 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000672 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500673 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
674 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500675 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500676 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000677 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
678 stat(FileName.c_str(), &st);
679 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500680 if (de->d_type == DT_REG) {
681 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000682 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500683 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000684 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
685 *thread_id = *thread_id + 1;
686 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500687 }
688 }
689 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000690 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500691 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500692}
693
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500694int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000695 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000696 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500697 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500698 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500699 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
700 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500701 return -1;
702 }
703 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500704 LOGINFO("Unable to close tar file\n");
705 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500706 return -1;
707 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600708#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500709 if (part_settings->adbbackup) {
710 if (!twadbbu::Write_TWEOF())
711 return -1;
712 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600713#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500714 return 0;
715}
716
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500717int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500718 if (!part_settings->adbbackup) {
719 LOGINFO("Setting archive type\n");
720 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
721 }
722 else {
723 if (part_settings->adb_compression == 1)
724 current_archive_type = COMPRESSED;
725 else
726 current_archive_type = UNCOMPRESSED;
727 }
n0d33b511632013-03-06 21:14:15 +0200728
bigbiffce8f83c2015-12-12 18:30:21 -0500729 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500730 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000731 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000732 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500733 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500734 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600735 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000736 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500737 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000738 return -1;
739 }
740 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500741 LOGINFO("Decrypted file is not in tar format.\n");
742 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000743 return -1;
744 }
745 if (ret == 3) {
746 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500747 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000748 } else
749 LOGINFO("Extracting encrypted tar.\n");
750 return extractTar();
751 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000752 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500753 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500754 }
755}
756
Dees Troye0a433a2013-12-02 04:10:37 +0000757int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000758 struct stat st;
759 char buf[PATH_MAX];
760 int list_size = TarList->size(), i = 0, archive_count = 0;
761 string temp;
762 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000763 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500764 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000765
Dees Troye0a433a2013-12-02 04:10:37 +0000766 if (split_archives) {
767 basefn = tarfn;
768 temp = basefn + "%i%02i";
769 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
770 tarfn = actual_filename;
771 include_root_dir = true;
772 } else {
773 include_root_dir = false;
774 }
bigbiffce8f83c2015-12-12 18:30:21 -0500775
776 if (part_settings->adbbackup)
777 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
778 else
779 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
780
Dees_Troy83bd4832013-05-04 12:39:56 +0000781 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500782 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
783 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000784 return -2;
785 }
786 Archive_Current_Size = 0;
787
788 while (i < list_size) {
789 if (TarList->at(i).thread_id == thread_id) {
790 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400791 lstat(buf, &st);
792 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500793 fs = (unsigned long long)(st.st_size);
794 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000795 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500796 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
797 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000798 return -3;
799 }
800 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500801 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000802 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500803 LOGINFO("Too many archives for thread %i\n", thread_id);
804 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000805 return -4;
806 }
807 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
808 tarfn = actual_filename;
809 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500810 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
811 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000812 return -2;
813 }
814 Archive_Current_Size = 0;
815 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500816 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600817 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500818 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000819 }
Dees Troye0a433a2013-12-02 04:10:37 +0000820 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
821 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500822 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
823 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000824 return -1;
825 }
826 }
827 i++;
828 }
829 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500830 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
831 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000832 return -3;
833 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600834 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000835 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500836}
837
Dees_Troy83bd4832013-05-04 12:39:56 +0000838void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000839 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600840 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000841 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
842 return (void*)-2;
843 }
844 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
845 return (void*)0;
846}
847
848void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000849 twrpTar* threadTar = (twrpTar*) cookie;
850 int archive_count = 0;
851 string temp = threadTar->basefn + "%i%02i";
852 char actual_filename[255];
853 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
854 while (TWFunc::Path_Exists(actual_filename)) {
855 threadTar->tarfn = actual_filename;
856 if (threadTar->extract() != 0) {
857 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
858 return (void*)-2;
859 }
860 archive_count++;
861 if (archive_count > 99)
862 break;
863 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
864 }
865 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
866 return (void*)0;
867}
868
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500869int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
870 char* charTarFile = (char*) fn.c_str();
871
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200872 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 -0500873 return -1;
874 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200875 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 -0500876 return -1;
877 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500878 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500879 if (tar_append_file(t, file, file) == -1)
880 return -1;
881 }
882 if (tar_append_eof(t) == -1)
883 return -1;
884 if (tar_close(t) == -1)
885 return -1;
886 return 0;
887}
888
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500889int twrpTar::createTar() {
890 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000891 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500892
Dees_Troy83bd4832013-05-04 12:39:56 +0000893 if (use_encryption && use_compression) {
894 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500895 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000896 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000897 int i, pipes[4];
898
899 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500900 LOGINFO("Error creating first pipe\n");
901 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500902 return -1;
903 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000904 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500905 LOGINFO("Error creating second pipe\n");
906 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500907 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000908 }
bigbiffce8f83c2015-12-12 18:30:21 -0500909 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 +0000910 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500911 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000912 for (i = 0; i < 4; i++)
913 close(pipes[i]); // close all
914 return -1;
915 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000916 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400917
Dees_Troy83bd4832013-05-04 12:39:56 +0000918 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500919 LOGINFO("pigz fork() failed\n");
920 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000921 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000922 for (i = 0; i < 4; i++)
923 close(pipes[i]); // close all
924 return -1;
925 } else if (pigz_pid == 0) {
926 // pigz Child
927 close(pipes[1]);
928 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500929 int stdinfd = fileno(stdin);
930 int stdoutfd = fileno(stdout);
931 close(stdinfd);
932 dup2(pipes[0], stdinfd);
933 close(stdoutfd);
934 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000935 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500936 LOGINFO("execlp pigz ERROR!\n");
937 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000938 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000939 close(pipes[0]);
940 close(pipes[3]);
941 _exit(-1);
942 }
943 } else {
944 // Parent
945 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400946
Dees_Troy83bd4832013-05-04 12:39:56 +0000947 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500948 LOGINFO("openaes fork() failed\n");
949 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000950 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000951 for (i = 0; i < 4; i++)
952 close(pipes[i]); // close all
953 return -1;
954 } else if (oaes_pid == 0) {
955 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000956 close(pipes[0]);
957 close(pipes[1]);
958 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500959 int stdinfd = fileno(stdin);
960 int stdoutfd = fileno(stdout);
961 close(stdinfd);
962 dup2(pipes[2], stdinfd);
963 close(stdoutfd);
964 dup2(output_fd, stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -0600965 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500966 LOGINFO("execlp openaes ERROR!\n");
967 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000968 close(pipes[2]);
969 close(output_fd);
970 _exit(-1);
971 }
972 } else {
973 // Parent
974 close(pipes[0]);
975 close(pipes[2]);
976 close(pipes[3]);
977 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600978 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500979 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker472f5062016-02-25 13:47:30 -0600980 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 +0000981 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500982 LOGINFO("tar_fdopen failed\n");
983 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000984 return -1;
985 }
986 return 0;
987 }
988 }
989 } else if (use_compression) {
990 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500991 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000992 LOGINFO("Using compression...\n");
993 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500994 if (part_settings->adbbackup) {
995 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
996 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
997 }
998 else {
999 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);
1000 }
Dees Troy9d723272014-04-07 17:13:10 +00001001 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001002 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001003 close(pigzfd[0]);
1004 return -1;
1005 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001006
1007 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001008 LOGINFO("Error creating pipe\n");
1009 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001010 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001011 return -1;
1012 }
1013 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001014
Dees_Troy83bd4832013-05-04 12:39:56 +00001015 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001016 LOGINFO("fork() failed\n");
1017 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001018 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001019 close(pigzfd[0]);
1020 close(pigzfd[1]);
1021 return -1;
1022 } else if (pigz_pid == 0) {
1023 // Child
1024 close(pigzfd[1]); // close unused output pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001025 dup2(pigzfd[0], fileno(stdin)); // remap stdin
1026 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001027 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001028 LOGINFO("execlp pigz ERROR!\n");
1029 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001030 close(output_fd);
1031 close(pigzfd[0]);
1032 _exit(-1);
1033 }
1034 } else {
1035 // Parent
1036 close(pigzfd[0]); // close parent input
1037 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001038 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001039 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker472f5062016-02-25 13:47:30 -06001040 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 +00001041 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001042 LOGINFO("tar_fdopen failed\n");
1043 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001044 return -1;
1045 }
1046 }
1047 } else if (use_encryption) {
1048 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001049 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001050 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001051 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001052 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 +00001053 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001054 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001055 return -1;
1056 }
1057 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001058 LOGINFO("Error creating pipe\n");
1059 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001060 close(output_fd);
1061 return -1;
1062 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001063 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001064
Dees_Troy83bd4832013-05-04 12:39:56 +00001065 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001066 LOGINFO("fork() failed\n");
1067 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001068 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001069 close(oaesfd[0]);
1070 close(oaesfd[1]);
1071 return -1;
1072 } else if (oaes_pid == 0) {
1073 // Child
1074 close(oaesfd[1]); // close unused
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001075 dup2(oaesfd[0], fileno(stdin)); // remap stdin
1076 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001077 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001078 LOGINFO("execlp openaes ERROR!\n");
1079 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001080 close(output_fd);
1081 close(oaesfd[0]);
1082 _exit(-1);
1083 }
1084 } else {
1085 // Parent
1086 close(oaesfd[0]); // close parent input
1087 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001088 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001089 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker472f5062016-02-25 13:47:30 -06001090 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 +00001091 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001092 LOGINFO("tar_fdopen failed\n");
1093 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001094 return -1;
1095 }
1096 return 0;
1097 }
1098 } else {
1099 // Not compressed or encrypted
Ethan Yonker472f5062016-02-25 13:47:30 -06001100 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001101 if (part_settings->adbbackup) {
1102 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001103 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001104 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1105 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) {
1106 close(output_fd);
1107 LOGERR("tar_fdopen failed\n");
1108 return -1;
1109 }
1110 }
1111 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001112 tar_type.writefunc = write_tar;
bigbiffce8f83c2015-12-12 18:30:21 -05001113 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) {
1114 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1115 gui_err("backup_error=Error creating backup.");
1116 return -1;
1117 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001118 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001119 }
1120 return 0;
1121}
1122
Dees_Troy83bd4832013-05-04 12:39:56 +00001123int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001124 char* charRootDir = (char*) tardir.c_str();
1125 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001126 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001127
bigbiffce8f83c2015-12-12 18:30:21 -05001128 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001129 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001130 int i, pipes[4];
bigbiffce8f83c2015-12-12 18:30:21 -05001131 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001132 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001133 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001134 return -1;
1135 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001136
1137 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001138 LOGINFO("Error creating first pipe\n");
1139 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001140 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001141 return -1;
1142 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001143 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001144 LOGINFO("Error creating second pipe\n");
1145 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001146 close(pipes[0]);
1147 close(pipes[1]);
1148 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001149 return -1;
1150 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001151 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001152
Dees_Troy83bd4832013-05-04 12:39:56 +00001153 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001154 LOGINFO("pigz fork() failed\n");
1155 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001156 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001157 for (i = 0; i < 4; i++)
1158 close(pipes[i]); // close all
1159 return -1;
1160 } else if (oaes_pid == 0) {
1161 // openaes Child
1162 close(pipes[0]); // Close pipes that are not used by this child
1163 close(pipes[2]);
1164 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001165 int stdinfd = fileno(stdin);
1166 int stdoutfd = fileno(stdout);
1167 close(stdinfd);
1168 dup2(input_fd, stdinfd);
1169 close(stdoutfd);
1170 dup2(pipes[1], stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -06001171 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001172 LOGINFO("execlp openaes ERROR!\n");
1173 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001174 close(input_fd);
1175 close(pipes[1]);
1176 _exit(-1);
1177 }
1178 } else {
1179 // Parent
1180 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001181
Dees_Troy83bd4832013-05-04 12:39:56 +00001182 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001183 LOGINFO("openaes fork() failed\n");
1184 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001185 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001186 for (i = 0; i < 4; i++)
1187 close(pipes[i]); // close all
1188 return -1;
1189 } else if (pigz_pid == 0) {
1190 // pigz Child
1191 close(pipes[1]); // Close pipes not used by this child
1192 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001193 int stdinfd = fileno(stdin);
1194 int stdoutfd = fileno(stdout);
1195 close(stdinfd);
1196 dup2(pipes[0], stdinfd);
1197 close(stdoutfd);
1198 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001199 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001200 LOGINFO("execlp pigz ERROR!\n");
1201 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001202 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001203 close(pipes[0]);
1204 close(pipes[3]);
1205 _exit(-1);
1206 }
1207 } else {
1208 // Parent
1209 close(pipes[0]); // Close pipes not used by parent
1210 close(pipes[1]);
1211 close(pipes[3]);
1212 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001213 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 +00001214 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001215 LOGINFO("tar_fdopen failed\n");
1216 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001217 return -1;
1218 }
1219 }
1220 }
bigbiffce8f83c2015-12-12 18:30:21 -05001221 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001222 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001223 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001224 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001225 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001226 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001227 return -1;
1228 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001229
Dees Troy9d723272014-04-07 17:13:10 +00001230 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001231 LOGINFO("Error creating pipe\n");
1232 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001233 close(input_fd);
1234 return -1;
1235 }
1236
Dees_Troy83bd4832013-05-04 12:39:56 +00001237 oaes_pid = fork();
1238 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001239 LOGINFO("fork() failed\n");
1240 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001241 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001242 close(oaesfd[0]);
1243 close(oaesfd[1]);
1244 return -1;
1245 } else if (oaes_pid == 0) {
1246 // Child
1247 close(oaesfd[0]); // Close unused pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001248 int stdinfd = fileno(stdin);
1249 close(stdinfd); // close stdin
1250 dup2(oaesfd[1], fileno(stdout)); // remap stdout
1251 dup2(input_fd, stdinfd); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001252 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001253 LOGINFO("execlp openaes ERROR!\n");
1254 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001255 close(input_fd);
1256 close(oaesfd[1]);
1257 _exit(-1);
1258 }
1259 } else {
1260 // Parent
1261 close(oaesfd[1]); // close parent output
1262 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001263 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 +00001264 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001265 LOGINFO("tar_fdopen failed\n");
1266 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001267 return -1;
1268 }
1269 }
bigbiffce8f83c2015-12-12 18:30:21 -05001270 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001271 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001272
1273 LOGINFO("Opening as a gzip...\n");
1274 if (part_settings->adbbackup) {
1275 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
1276 input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE);
1277 }
1278 else
1279 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1280
Dees Troy9d723272014-04-07 17:13:10 +00001281 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001282 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001283 return -1;
1284 }
bigbiffce8f83c2015-12-12 18:30:21 -05001285
Dees Troy9d723272014-04-07 17:13:10 +00001286 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001287 LOGINFO("Error creating pipe\n");
1288 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001289 close(input_fd);
1290 return -1;
1291 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001292
1293 pigz_pid = fork();
1294 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001295 LOGINFO("fork() failed\n");
1296 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001297 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001298 close(pigzfd[0]);
1299 close(pigzfd[1]);
1300 return -1;
1301 } else if (pigz_pid == 0) {
1302 // Child
1303 close(pigzfd[0]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001304 dup2(pigzfd[1], fileno(stdout)); // remap stdout
1305 dup2(input_fd, fileno(stdin)); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001306 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1307 close(pigzfd[1]);
1308 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001309 LOGINFO("execlp openaes ERROR!\n");
1310 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001311 _exit(-1);
1312 }
1313 } else {
1314 // Parent
1315 close(pigzfd[1]); // close parent output
1316 fd = pigzfd[0]; // copy parent input
bigbiffce8f83c2015-12-12 18:30:21 -05001317 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 +00001318 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001319 LOGINFO("tar_fdopen failed\n");
1320 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001321 return -1;
1322 }
1323 }
bigbiffce8f83c2015-12-12 18:30:21 -05001324 } else {
1325 if (part_settings->adbbackup) {
1326 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1327 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
1328 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) {
1329 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1330 gui_err("restore_error=Error during restore process.");
1331 return -1;
1332 }
1333 }
1334 else {
1335 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) {
1336 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1337 gui_err("restore_error=Error during restore process.");
1338 return -1;
1339 }
1340 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001341 }
1342 return 0;
1343}
1344
1345string twrpTar::Strip_Root_Dir(string Path) {
1346 string temp;
1347 size_t slash;
1348
1349 if (Path.substr(0, 1) == "/")
1350 temp = Path.substr(1, Path.size() - 1);
1351 else
1352 temp = Path;
1353 slash = temp.find("/");
1354 if (slash == string::npos)
1355 return temp;
1356 else {
1357 string stripped;
1358
1359 stripped = temp.substr(slash, temp.size() - slash);
1360 return stripped;
1361 }
1362 return temp;
1363}
1364
1365int twrpTar::addFile(string fn, bool include_root) {
1366 char* charTarFile = (char*) fn.c_str();
1367 if (include_root) {
1368 if (tar_append_file(t, charTarFile, NULL) == -1)
1369 return -1;
1370 } else {
1371 string temp = Strip_Root_Dir(fn);
1372 char* charTarPath = (char*) temp.c_str();
1373 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1374 return -1;
1375 }
1376 return 0;
1377}
1378
Dees_Troy83bd4832013-05-04 12:39:56 +00001379int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001380 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001381 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001382 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001383 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001384 tar_close(t);
1385 return -1;
1386 }
1387 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001388 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001389 return -1;
1390 }
bigbiffce8f83c2015-12-12 18:30:21 -05001391 if (current_archive_type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001392 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001393 int status;
1394 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1395 return -1;
1396 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1397 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001398 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001399 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001400 if (!part_settings->adbbackup) {
1401 if (use_compression && !use_encryption) {
1402 string gzname = tarfn + ".gz";
1403 if (TWFunc::Path_Exists(gzname)) {
1404 rename(gzname.c_str(), tarfn.c_str());
1405 }
Dees Troye0a433a2013-12-02 04:10:37 +00001406 }
bigbiffce8f83c2015-12-12 18:30:21 -05001407 if (TWFunc::Get_File_Size(tarfn) == 0) {
1408 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1409 return -1;
1410 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001411#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001412 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001413#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001414 }
1415 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001416#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001417 if (!twadbbu::Write_TWEOF())
1418 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001419#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001420 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001421 if (input_fd >= 0)
1422 close(input_fd);
1423 if (output_fd >= 0)
1424 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001425 return 0;
1426}
1427
1428int twrpTar::removeEOT(string tarFile) {
1429 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001430 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001431 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001432 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001433 tar_skip_regfile(t);
1434 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001435 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001436 if (tar_close(t) == -1)
1437 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001438 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001439 return -1;
1440 return 0;
1441}
1442
n0d33b511632013-03-06 21:14:15 +02001443int twrpTar::entryExists(string entry) {
1444 char* searchstr = (char*)entry.c_str();
1445 int ret;
1446
bigbiffce8f83c2015-12-12 18:30:21 -05001447 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001448
Dees_Troy83bd4832013-05-04 12:39:56 +00001449 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001450 ret = 0;
1451 else
1452 ret = tar_find(t, searchstr);
1453
Dees_Troy83bd4832013-05-04 12:39:56 +00001454 if (closeTar() != 0)
1455 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001456
1457 return ret;
1458}
1459
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001460unsigned long long twrpTar::get_size() {
bigbiffce8f83c2015-12-12 18:30:21 -05001461 if (TWFunc::Path_Exists(tarfn) && !part_settings->adbbackup) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001462 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001463 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001464 } else {
1465 LOGINFO("Multiple archives\n");
1466 string temp;
1467 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001468 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001469 unsigned long long total_restore_size = 0;
1470
1471 basefn = tarfn;
1472 temp = basefn + "%i%02i";
1473 tarfn += "000";
1474 thread_id = 0;
1475 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001476 if (!part_settings->adbbackup) {
1477 if (!TWFunc::Path_Exists(actual_filename)) {
1478 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1479 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001480 }
bigbiffce8f83c2015-12-12 18:30:21 -05001481 for (int i = 0; i < 9; i++) {
1482 archive_count = 0;
1483 sprintf(actual_filename, temp.c_str(), i, archive_count);
1484 while (TWFunc::Path_Exists(actual_filename)) {
1485 total_restore_size += uncompressedSize(actual_filename);
1486 archive_count++;
1487 if (archive_count > 99)
1488 break;
1489 sprintf(actual_filename, temp.c_str(), i, archive_count);
1490 }
1491 }
1492 #ifndef BUILD_TWRPTAR_MAIN
1493 if (!part_settings->adbbackup) {
1494 InfoManager backup_info(tarfn + ".info");
1495 backup_info.SetValue("backup_size", total_restore_size);
1496 backup_info.SetValue("backup_type", current_archive_type);
1497 backup_info.SaveValues();
1498 }
1499 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001500 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001501 return total_restore_size;
1502 }
1503 return 0;
1504}
1505
bigbiffce8f83c2015-12-12 18:30:21 -05001506unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001507 unsigned long long total_size = 0;
1508 string Tar, Command, result;
1509 vector<string> split;
1510
bigbiffce8f83c2015-12-12 18:30:21 -05001511 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1512 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001513 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001514 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001515 // Compressed
1516 Command = "pigz -l '" + filename + "'";
1517 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1518 we get the uncompressed size at once. */
1519 TWFunc::Exec_Cmd(Command, result);
1520 if (!result.empty()) {
1521 /* Expected output:
1522 compressed original reduced name
1523 95855838 179403776 -1.3% data.yaffs2.win
1524 ^
1525 split[5]
1526 */
1527 split = TWFunc::split_string(result, ' ', true);
1528 if (split.size() > 4)
1529 total_size = atoi(split[5].c_str());
1530 }
bigbiffce8f83c2015-12-12 18:30:21 -05001531 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001532 // File is encrypted and may be compressed
1533 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001534 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001535 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001536 total_size = TWFunc::Get_File_Size(filename);
1537 } else if (ret == 1) {
1538 LOGERR("Decrypted file is not in tar format.\n");
1539 total_size = TWFunc::Get_File_Size(filename);
1540 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001541 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1542 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1543 we get the uncompressed size at once. */
1544 TWFunc::Exec_Cmd(Command, result);
1545 if (!result.empty()) {
1546 LOGINFO("result was: '%s'\n", result.c_str());
1547 /* Expected output:
1548 compressed original reduced name
1549 95855838 179403776 -1.3% data.yaffs2.win
1550 ^
1551 split[5]
1552 */
1553 split = TWFunc::split_string(result, ' ', true);
1554 if (split.size() > 4)
1555 total_size = atoi(split[5].c_str());
1556 }
1557 } else {
1558 total_size = TWFunc::Get_File_Size(filename);
1559 }
1560 }
1561
1562 return total_size;
1563}
1564
Dees_Troye34c1332013-02-06 19:13:00 +00001565extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1566 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001567}
Ethan Yonker472f5062016-02-25 13:47:30 -06001568
1569extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1570 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1571}