blob: dcbb28202ab796aafb1da981231e2c42c7f27bcf [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;
Dees_Troy83bd4832013-05-04 12:39:56 +000072}
73
74twrpTar::~twrpTar(void) {
75 // Do nothing
76}
77
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050078void twrpTar::setfn(string fn) {
79 tarfn = fn;
80}
81
82void twrpTar::setdir(string dir) {
83 tardir = dir;
84}
85
Dees Troye0a433a2013-12-02 04:10:37 +000086void twrpTar::setsize(unsigned long long backup_size) {
87 Total_Backup_Size = backup_size;
88}
89
Ethan Yonker87af5632014-02-10 11:56:35 -060090void twrpTar::setpassword(string pass) {
91 password = pass;
92}
93
bigbiff7abc5fe2015-01-17 16:53:12 -050094void twrpTar::Signal_Kill(int signum) {
95 _exit(255);
96}
97
bigbiffce8f83c2015-12-12 18:30:21 -050098void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
99 current_archive_type = archive_type;
100}
101
102int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000103 int status = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500104 pid_t rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500105 int progress_pipe[2], ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500106 char cmd[512];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500107
108 file_count = 0;
109
bigbiffce8f83c2015-12-12 18:30:21 -0500110 if (part_settings->adbbackup) {
111 std::string Backup_FileName(tarfn);
112 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
113 return -1;
114 }
115
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500116 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500117 LOGINFO("Error creating progress tracking pipe\n");
118 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500119 return -1;
120 }
bigbiffce8f83c2015-12-12 18:30:21 -0500121 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000122 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500123 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500124 close(progress_pipe[0]);
125 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500126 return -1;
127 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500128
bigbiffce8f83c2015-12-12 18:30:21 -0500129 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500130 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500131 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500132 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500133 close(progress_pipe[0]);
134 progress_pipe_fd = progress_pipe[1];
135
Dees_Troy83bd4832013-05-04 12:39:56 +0000136 if (use_encryption || userdata_encryption) {
137 LOGINFO("Using encryption\n");
138 DIR* d;
139 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200140 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
141 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000142 int item_len, ret, thread_error = 0;
143 std::vector<TarListStruct> RegularList;
144 std::vector<TarListStruct> EncryptList;
145 string FileName;
146 struct TarListStruct TarItem;
147 twrpTar reg, enc[9];
148 struct stat st;
149 pthread_t enc_thread[9];
150 pthread_attr_t tattr;
151 void *thread_return;
152
153 core_count = sysconf(_SC_NPROCESSORS_CONF);
154 if (core_count > 8)
155 core_count = 8;
that2252d242015-04-03 22:33:04 +0200156 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000157 Archive_Current_Size = 0;
158
159 d = opendir(tardir.c_str());
160 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500161 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500162 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000163 _exit(-1);
164 }
165 // Figure out the size of all data to be encrypted and create a list of unencrypted files
166 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500167 FileName = tardir + "/" + de->d_name;
168
169 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000170 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500171 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000172 item_len = strlen(de->d_name);
173 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 -0500174 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
175 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500176 LOGINFO("Error in Generate_TarList with regular list!\n");
177 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000178 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500179 close(progress_pipe_fd);
180 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000181 _exit(-1);
182 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500183 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500184 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000185 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500186 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000187 }
188 } else if (de->d_type == DT_REG) {
189 stat(FileName.c_str(), &st);
190 encrypt_size += (unsigned long long)(st.st_size);
191 }
192 }
193 closedir(d);
194
195 target_size = encrypt_size / core_count;
196 target_size++;
197 LOGINFO(" Unencrypted size: %llu\n", regular_size);
198 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
199 LOGINFO(" Target size : %llu\n", target_size);
200 if (!userdata_encryption) {
201 enc_thread_id = 0;
202 start_thread_id = 0;
203 core_count--;
204 }
205 Archive_Current_Size = 0;
206
207 d = opendir(tardir.c_str());
208 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500209 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500210 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000211 _exit(-1);
212 }
213 // Divide up the encrypted file list for threading
214 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500215 FileName = tardir + "/" + de->d_name;
216
217 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000218 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500219 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000220 item_len = strlen(de->d_name);
221 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
222 // Do nothing, we added these to RegularList earlier
223 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500224 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500225 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
226 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500227 LOGINFO("Error in Generate_TarList with encrypted list!\n");
228 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000229 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500230 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000231 _exit(-1);
232 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500233 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000234 }
235 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
236 stat(FileName.c_str(), &st);
237 if (de->d_type == DT_REG)
238 Archive_Current_Size += (unsigned long long)(st.st_size);
239 TarItem.fn = FileName;
240 TarItem.thread_id = enc_thread_id;
241 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 }
244 }
245 closedir(d);
246 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500247 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 -0500248 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500249 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500250 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000251 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500252 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500253 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500254 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000255 }
256
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500257 // Send file count to parent
258 write(progress_pipe_fd, &file_count, sizeof(file_count));
259 // Send backup size to parent
260 total_size = regular_size + encrypt_size;
261 write(progress_pipe_fd, &total_size, sizeof(total_size));
262
Dees_Troy83bd4832013-05-04 12:39:56 +0000263 if (userdata_encryption) {
264 // Create a backup of unencrypted data
265 reg.setfn(tarfn);
266 reg.ItemList = &RegularList;
267 reg.thread_id = 0;
268 reg.use_encryption = 0;
269 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000270 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500271 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500272 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000273 LOGINFO("Creating unencrypted backup...\n");
274 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500275 LOGINFO("Error creating unencrypted backup.\n");
276 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500277 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000278 _exit(-1);
279 }
280 }
281
282 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500283 LOGINFO("Unable to pthread_attr_init\n");
284 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500285 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000286 _exit(-1);
287 }
288 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500289 LOGINFO("Error setting pthread_attr_setdetachstate\n");
290 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500291 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000292 _exit(-1);
293 }
294 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500295 LOGINFO("Error setting pthread_attr_setscope\n");
296 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500297 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000298 _exit(-1);
299 }
300 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
301 LOGERR("Error setting pthread_attr_setstacksize\n");
302 _exit(-1);
303 }*/
304
305 // Create threads for the divided up encryption lists
306 for (i = start_thread_id; i <= core_count; i++) {
307 enc[i].setdir(tardir);
308 enc[i].setfn(tarfn);
309 enc[i].ItemList = &EncryptList;
310 enc[i].thread_id = i;
311 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500312 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000313 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000314 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500315 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500316 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000317 LOGINFO("Start encryption thread %i\n", i);
318 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
319 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500320 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 +0000321 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500322 LOGINFO("Error creating encrypted backup %i.\n", i);
323 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500324 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000325 _exit(-1);
326 } else {
327 enc[i].thread_id = i + 1;
328 }
329 }
330 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
331 }
332 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500333 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000334 }
335 for (i = start_thread_id; i <= core_count; i++) {
336 if (enc[i].thread_id == i) {
337 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500338 LOGINFO("Error joining thread %i\n", i);
339 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500340 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000341 _exit(-1);
342 } else {
343 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200344 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000345 if (ret != 0) {
346 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500347 LOGINFO("Thread %i returned an error %i.\n", i, ret);
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 }
352 }
353 } else {
354 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
355 }
356 }
357 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500358 LOGINFO("Error returned by one or more threads.\n");
359 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500360 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000361 _exit(-1);
362 }
363 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500364 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000365 _exit(0);
366 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500367 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000368 std::vector<TarListStruct> FileList;
369 unsigned thread_id = 0;
370 unsigned long long target_size = 0;
371 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500372 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000373
374 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500375 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
376 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500377 LOGINFO("Error in Generate_TarList!\n");
378 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500379 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000380 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000381 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500382 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000383 // Create a backup
384 reg.setfn(tarfn);
385 reg.ItemList = &FileList;
386 reg.thread_id = 0;
387 reg.use_encryption = 0;
388 reg.use_compression = use_compression;
389 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500390 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500391 reg.part_settings = part_settings;
392 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500393 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000394 reg.split_archives = 1;
395 } else {
396 reg.split_archives = 0;
397 }
398 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500399 write(progress_pipe_fd, &file_count, sizeof(file_count));
400 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000401 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500402 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500403 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000404 _exit(-1);
405 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500406 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000407 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000408 }
409 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500410 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600411 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500412 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500413
414 // Parent closes output side
415 close(progress_pipe[1]);
416
417 // Read progress data from children
418 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
419 if (first_data == 0) {
420 // First incoming data is the file count
421 file_count = fs;
422 if (file_count == 0) file_count = 1; // prevent division by 0 below
423 first_data = 1;
424 } else if (first_data == 1) {
425 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500426 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500427 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500428 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600429 if (fs > 0) {
430 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500431 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600432 } else { // fs == 0 increments the file counter
433 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500434 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600435 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500436 }
437 }
438 close(progress_pipe[0]);
439#ifndef BUILD_TWRPTAR_MAIN
440 DataManager::SetValue("tw_file_progress", "");
441 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500442 part_settings->progress->DisplayFileCount(false);
443 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500444
bigbiffce8f83c2015-12-12 18:30:21 -0500445 if (!part_settings->adbbackup) {
446 InfoManager backup_info(backup_folder + partition_name + ".info");
447 backup_info.SetValue("backup_size", size_backup);
448 if (use_compression && use_encryption)
449 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
450 else if (use_encryption)
451 backup_info.SetValue("backup_type", ENCRYPTED);
452 else if (use_compression)
453 backup_info.SetValue("backup_type", COMPRESSED);
454 else
455 backup_info.SetValue("backup_type", UNCOMPRESSED);
456 backup_info.SetValue("file_count", files_backup);
457 backup_info.SaveValues();
458 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500459#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500460 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500461 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500462 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500463 return 0;
464}
465
bigbiffce8f83c2015-12-12 18:30:21 -0500466int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000467 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500468 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500469 int progress_pipe[2], ret;
470
471 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500472 LOGINFO("Error creating progress tracking pipe\n");
473 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500474 return -1;
475 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000476
bigbiff7abc5fe2015-01-17 16:53:12 -0500477 tar_fork_pid = fork();
478 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000479 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500480 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000481 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500482 close(progress_pipe[0]);
483 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500484 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000485 LOGINFO("Single archive\n");
486 if (extract() != 0)
487 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500488 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000489 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500490 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000491 } else {
492 LOGINFO("Multiple archives\n");
493 string temp;
494 char actual_filename[255];
495 twrpTar tars[9];
496 pthread_t tar_thread[9];
497 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500498 unsigned thread_count = 0, i, start_thread_id = 1;
499 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000500 void *thread_return;
501
502 basefn = tarfn;
503 temp = basefn + "%i%02i";
504 tarfn += "000";
505 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500506 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
507 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500508 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000509 _exit(-1);
510 }
511 if (TWFunc::Get_File_Type(tarfn) != 2) {
512 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
513 tars[0].basefn = basefn;
514 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500515 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500516 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000517 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500518 LOGINFO("Error extracting split archive.\n");
519 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500520 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000521 _exit(-1);
522 }
523 } else {
524 start_thread_id = 0;
525 }
526 // Start threading encrypted restores
527 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500528 LOGINFO("Unable to pthread_attr_init\n");
529 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500530 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000531 _exit(-1);
532 }
533 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500534 LOGINFO("Error setting pthread_attr_setdetachstate\n");
535 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500536 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000537 _exit(-1);
538 }
539 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500540 LOGINFO("Error setting pthread_attr_setscope\n");
541 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500542 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000543 _exit(-1);
544 }
545 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
546 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500547 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000548 _exit(-1);
549 }*/
550 for (i = start_thread_id; i < 9; i++) {
551 sprintf(actual_filename, temp.c_str(), i, 0);
552 if (TWFunc::Path_Exists(actual_filename)) {
553 thread_count++;
554 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500555 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000556 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500557 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500558 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000559 LOGINFO("Creating extract thread ID %i\n", i);
560 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
561 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500562 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 +0000563 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500564 LOGINFO("Error extracting backup in thread %i.\n", i);
565 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500566 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000567 _exit(-1);
568 } else {
569 tars[i].thread_id = i + 1;
570 }
571 }
572 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
573 } else {
574 break;
575 }
576 }
577 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
578 if (tars[i].thread_id == i) {
579 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500580 LOGINFO("Error joining thread %i\n", i);
581 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500582 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000583 _exit(-1);
584 } else {
585 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200586 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000587 if (ret != 0) {
588 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500589 LOGINFO("Thread %i returned an error %i.\n", i, ret);
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 }
594 }
595 } else {
596 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
597 }
598 }
599 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500600 LOGINFO("Error returned by one or more threads.\n");
601 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500602 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000603 _exit(-1);
604 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500605 LOGINFO("Finished encrypted restore.\n");
606 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000607 _exit(0);
608 }
609 }
610 else // parent process
611 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600612 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500613
614 // Parent closes output side
615 close(progress_pipe[1]);
616
617 // Read progress data from children
618 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
619 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500620 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500621 }
622 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500623 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500624
bigbiff7abc5fe2015-01-17 16:53:12 -0500625 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000626 return -1;
627 }
628 }
629 else // fork has failed
630 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500631 close(progress_pipe[0]);
632 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000633 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500634 return -1;
635 }
636 return 0;
637}
638
Dees_Troy83bd4832013-05-04 12:39:56 +0000639int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
640 DIR* d;
641 struct dirent* de;
642 struct stat st;
643 string FileName;
644 struct TarListStruct TarItem;
645 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500646 int ret, file_count;
647 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000648
Dees_Troy83bd4832013-05-04 12:39:56 +0000649 d = opendir(Path.c_str());
650 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500651 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000652 closedir(d);
653 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500654 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000655 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500656 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500657
Matt Mower50248ab2014-03-31 15:58:40 -0500658 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000659 continue;
660 TarItem.fn = FileName;
661 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500662 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000663 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500664 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
665 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500666 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500667 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000668 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
669 stat(FileName.c_str(), &st);
670 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500671 if (de->d_type == DT_REG) {
672 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000673 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500674 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000675 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
676 *thread_id = *thread_id + 1;
677 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500678 }
679 }
680 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000681 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500682 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500683}
684
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500685int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000686 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000687 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500688 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500689 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500690 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
691 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500692 return -1;
693 }
694 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500695 LOGINFO("Unable to close tar file\n");
696 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500697 return -1;
698 }
bigbiffce8f83c2015-12-12 18:30:21 -0500699 if (part_settings->adbbackup) {
700 if (!twadbbu::Write_TWEOF())
701 return -1;
702 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500703 return 0;
704}
705
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500706int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500707 if (!part_settings->adbbackup) {
708 LOGINFO("Setting archive type\n");
709 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
710 }
711 else {
712 if (part_settings->adb_compression == 1)
713 current_archive_type = COMPRESSED;
714 else
715 current_archive_type = UNCOMPRESSED;
716 }
n0d33b511632013-03-06 21:14:15 +0200717
bigbiffce8f83c2015-12-12 18:30:21 -0500718 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500719 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000720 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000721 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500722 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500723 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600724 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000725 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500726 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000727 return -1;
728 }
729 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500730 LOGINFO("Decrypted file is not in tar format.\n");
731 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000732 return -1;
733 }
734 if (ret == 3) {
735 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500736 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000737 } else
738 LOGINFO("Extracting encrypted tar.\n");
739 return extractTar();
740 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000741 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500742 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500743 }
744}
745
Dees Troye0a433a2013-12-02 04:10:37 +0000746int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000747 struct stat st;
748 char buf[PATH_MAX];
749 int list_size = TarList->size(), i = 0, archive_count = 0;
750 string temp;
751 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000752 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500753 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000754
Dees Troye0a433a2013-12-02 04:10:37 +0000755 if (split_archives) {
756 basefn = tarfn;
757 temp = basefn + "%i%02i";
758 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
759 tarfn = actual_filename;
760 include_root_dir = true;
761 } else {
762 include_root_dir = false;
763 }
bigbiffce8f83c2015-12-12 18:30:21 -0500764
765 if (part_settings->adbbackup)
766 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
767 else
768 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
769
Dees_Troy83bd4832013-05-04 12:39:56 +0000770 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500771 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
772 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000773 return -2;
774 }
775 Archive_Current_Size = 0;
776
777 while (i < list_size) {
778 if (TarList->at(i).thread_id == thread_id) {
779 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400780 lstat(buf, &st);
781 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500782 fs = (unsigned long long)(st.st_size);
783 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000784 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500785 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
786 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000787 return -3;
788 }
789 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500790 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000791 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500792 LOGINFO("Too many archives for thread %i\n", thread_id);
793 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000794 return -4;
795 }
796 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
797 tarfn = actual_filename;
798 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500799 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
800 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000801 return -2;
802 }
803 Archive_Current_Size = 0;
804 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500805 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600806 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500807 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000808 }
Dees Troye0a433a2013-12-02 04:10:37 +0000809 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
810 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500811 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
812 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000813 return -1;
814 }
815 }
816 i++;
817 }
818 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500819 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
820 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000821 return -3;
822 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600823 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000824 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500825}
826
Dees_Troy83bd4832013-05-04 12:39:56 +0000827void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000828 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600829 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
831 return (void*)-2;
832 }
833 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
834 return (void*)0;
835}
836
837void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000838 twrpTar* threadTar = (twrpTar*) cookie;
839 int archive_count = 0;
840 string temp = threadTar->basefn + "%i%02i";
841 char actual_filename[255];
842 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
843 while (TWFunc::Path_Exists(actual_filename)) {
844 threadTar->tarfn = actual_filename;
845 if (threadTar->extract() != 0) {
846 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
847 return (void*)-2;
848 }
849 archive_count++;
850 if (archive_count > 99)
851 break;
852 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
853 }
854 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
855 return (void*)0;
856}
857
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500858int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
859 char* charTarFile = (char*) fn.c_str();
860
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200861 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 -0500862 return -1;
863 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200864 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 -0500865 return -1;
866 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500867 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500868 if (tar_append_file(t, file, file) == -1)
869 return -1;
870 }
871 if (tar_append_eof(t) == -1)
872 return -1;
873 if (tar_close(t) == -1)
874 return -1;
875 return 0;
876}
877
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500878int twrpTar::createTar() {
879 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000880 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500881
Dees_Troy83bd4832013-05-04 12:39:56 +0000882 if (use_encryption && use_compression) {
883 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500884 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000885 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000886 int i, pipes[4];
887
888 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500889 LOGINFO("Error creating first pipe\n");
890 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500891 return -1;
892 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000893 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500894 LOGINFO("Error creating second pipe\n");
895 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500896 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000897 }
bigbiffce8f83c2015-12-12 18:30:21 -0500898 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 +0000899 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500900 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000901 for (i = 0; i < 4; i++)
902 close(pipes[i]); // close all
903 return -1;
904 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000905 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400906
Dees_Troy83bd4832013-05-04 12:39:56 +0000907 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500908 LOGINFO("pigz fork() failed\n");
909 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000910 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000911 for (i = 0; i < 4; i++)
912 close(pipes[i]); // close all
913 return -1;
914 } else if (pigz_pid == 0) {
915 // pigz Child
916 close(pipes[1]);
917 close(pipes[2]);
918 close(0);
919 dup2(pipes[0], 0);
920 close(1);
921 dup2(pipes[3], 1);
922 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500923 LOGINFO("execlp pigz ERROR!\n");
924 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000925 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000926 close(pipes[0]);
927 close(pipes[3]);
928 _exit(-1);
929 }
930 } else {
931 // Parent
932 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400933
Dees_Troy83bd4832013-05-04 12:39:56 +0000934 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500935 LOGINFO("openaes fork() failed\n");
936 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000937 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000938 for (i = 0; i < 4; i++)
939 close(pipes[i]); // close all
940 return -1;
941 } else if (oaes_pid == 0) {
942 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000943 close(pipes[0]);
944 close(pipes[1]);
945 close(pipes[3]);
946 close(0);
947 dup2(pipes[2], 0);
948 close(1);
949 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600950 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500951 LOGINFO("execlp openaes ERROR!\n");
952 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000953 close(pipes[2]);
954 close(output_fd);
955 _exit(-1);
956 }
957 } else {
958 // Parent
959 close(pipes[0]);
960 close(pipes[2]);
961 close(pipes[3]);
962 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600963 init_libtar_no_buffer(progress_pipe_fd);
964 tar_type = { open, close, read, write_tar_no_buffer };
965 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 +0000966 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500967 LOGINFO("tar_fdopen failed\n");
968 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000969 return -1;
970 }
971 return 0;
972 }
973 }
974 } else if (use_compression) {
975 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500976 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000977 LOGINFO("Using compression...\n");
978 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500979 if (part_settings->adbbackup) {
980 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
981 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
982 }
983 else {
984 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);
985 }
Dees Troy9d723272014-04-07 17:13:10 +0000986 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500987 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000988 close(pigzfd[0]);
989 return -1;
990 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000991
992 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500993 LOGINFO("Error creating pipe\n");
994 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000995 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000996 return -1;
997 }
998 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400999
Dees_Troy83bd4832013-05-04 12:39:56 +00001000 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001001 LOGINFO("fork() failed\n");
1002 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001003 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001004 close(pigzfd[0]);
1005 close(pigzfd[1]);
1006 return -1;
1007 } else if (pigz_pid == 0) {
1008 // Child
1009 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001010 dup2(pigzfd[0], 0); // remap stdin
1011 dup2(output_fd, 1); // remap stdout to output file
1012 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001013 LOGINFO("execlp pigz ERROR!\n");
1014 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001015 close(output_fd);
1016 close(pigzfd[0]);
1017 _exit(-1);
1018 }
1019 } else {
1020 // Parent
1021 close(pigzfd[0]); // close parent input
1022 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001023 init_libtar_no_buffer(progress_pipe_fd);
1024 tar_type = { open, close, read, write_tar_no_buffer };
1025 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 +00001026 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001027 LOGINFO("tar_fdopen failed\n");
1028 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001029 return -1;
1030 }
1031 }
1032 } else if (use_encryption) {
1033 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001034 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001035 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001036 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001037 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 +00001038 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001039 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001040 return -1;
1041 }
1042 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001043 LOGINFO("Error creating pipe\n");
1044 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001045 close(output_fd);
1046 return -1;
1047 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001048 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001049
Dees_Troy83bd4832013-05-04 12:39:56 +00001050 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001051 LOGINFO("fork() failed\n");
1052 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001053 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 close(oaesfd[0]);
1055 close(oaesfd[1]);
1056 return -1;
1057 } else if (oaes_pid == 0) {
1058 // Child
1059 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +00001060 dup2(oaesfd[0], 0); // remap stdin
1061 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001062 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001063 LOGINFO("execlp openaes ERROR!\n");
1064 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001065 close(output_fd);
1066 close(oaesfd[0]);
1067 _exit(-1);
1068 }
1069 } else {
1070 // Parent
1071 close(oaesfd[0]); // close parent input
1072 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001073 init_libtar_no_buffer(progress_pipe_fd);
1074 tar_type = { open, close, read, write_tar_no_buffer };
1075 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 +00001076 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001077 LOGINFO("tar_fdopen failed\n");
1078 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001079 return -1;
1080 }
1081 return 0;
1082 }
1083 } else {
1084 // Not compressed or encrypted
Ethan Yonker472f5062016-02-25 13:47:30 -06001085 init_libtar_buffer(0, progress_pipe_fd);
1086 tar_type = { open, close, read, write_tar };
bigbiffce8f83c2015-12-12 18:30:21 -05001087 if (part_settings->adbbackup) {
1088 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
1089 tar_type = { open, close, read, write_tar_no_buffer };
1090 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1091 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) {
1092 close(output_fd);
1093 LOGERR("tar_fdopen failed\n");
1094 return -1;
1095 }
1096 }
1097 else {
1098 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) {
1099 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1100 gui_err("backup_error=Error creating backup.");
1101 return -1;
1102 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001103 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001104 }
1105 return 0;
1106}
1107
Dees_Troy83bd4832013-05-04 12:39:56 +00001108int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001109 char* charRootDir = (char*) tardir.c_str();
1110 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001111 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001112
bigbiffce8f83c2015-12-12 18:30:21 -05001113 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001114 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001115 int i, pipes[4];
bigbiffce8f83c2015-12-12 18:30:21 -05001116 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001117 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001118 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001119 return -1;
1120 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001121
1122 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001123 LOGINFO("Error creating first pipe\n");
1124 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001125 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001126 return -1;
1127 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001128 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001129 LOGINFO("Error creating second pipe\n");
1130 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001131 close(pipes[0]);
1132 close(pipes[1]);
1133 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001134 return -1;
1135 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001136 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001137
Dees_Troy83bd4832013-05-04 12:39:56 +00001138 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001139 LOGINFO("pigz fork() failed\n");
1140 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001141 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001142 for (i = 0; i < 4; i++)
1143 close(pipes[i]); // close all
1144 return -1;
1145 } else if (oaes_pid == 0) {
1146 // openaes Child
1147 close(pipes[0]); // Close pipes that are not used by this child
1148 close(pipes[2]);
1149 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001150 close(0);
1151 dup2(input_fd, 0);
1152 close(1);
1153 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001154 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001155 LOGINFO("execlp openaes ERROR!\n");
1156 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001157 close(input_fd);
1158 close(pipes[1]);
1159 _exit(-1);
1160 }
1161 } else {
1162 // Parent
1163 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001164
Dees_Troy83bd4832013-05-04 12:39:56 +00001165 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001166 LOGINFO("openaes fork() failed\n");
1167 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001168 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001169 for (i = 0; i < 4; i++)
1170 close(pipes[i]); // close all
1171 return -1;
1172 } else if (pigz_pid == 0) {
1173 // pigz Child
1174 close(pipes[1]); // Close pipes not used by this child
1175 close(pipes[2]);
1176 close(0);
1177 dup2(pipes[0], 0);
1178 close(1);
1179 dup2(pipes[3], 1);
1180 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001181 LOGINFO("execlp pigz ERROR!\n");
1182 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001183 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001184 close(pipes[0]);
1185 close(pipes[3]);
1186 _exit(-1);
1187 }
1188 } else {
1189 // Parent
1190 close(pipes[0]); // Close pipes not used by parent
1191 close(pipes[1]);
1192 close(pipes[3]);
1193 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001194 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 +00001195 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001196 LOGINFO("tar_fdopen failed\n");
1197 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001198 return -1;
1199 }
1200 }
1201 }
bigbiffce8f83c2015-12-12 18:30:21 -05001202 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001203 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001204 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001205 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001206 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001207 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001208 return -1;
1209 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001210
Dees Troy9d723272014-04-07 17:13:10 +00001211 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001212 LOGINFO("Error creating pipe\n");
1213 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001214 close(input_fd);
1215 return -1;
1216 }
1217
Dees_Troy83bd4832013-05-04 12:39:56 +00001218 oaes_pid = fork();
1219 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001220 LOGINFO("fork() failed\n");
1221 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001222 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001223 close(oaesfd[0]);
1224 close(oaesfd[1]);
1225 return -1;
1226 } else if (oaes_pid == 0) {
1227 // Child
1228 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001229 close(0); // close stdin
1230 dup2(oaesfd[1], 1); // remap stdout
1231 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001232 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001233 LOGINFO("execlp openaes ERROR!\n");
1234 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001235 close(input_fd);
1236 close(oaesfd[1]);
1237 _exit(-1);
1238 }
1239 } else {
1240 // Parent
1241 close(oaesfd[1]); // close parent output
1242 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001243 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 +00001244 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001245 LOGINFO("tar_fdopen failed\n");
1246 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001247 return -1;
1248 }
1249 }
bigbiffce8f83c2015-12-12 18:30:21 -05001250 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001251 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001252
1253 LOGINFO("Opening as a gzip...\n");
1254 if (part_settings->adbbackup) {
1255 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
1256 input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE);
1257 }
1258 else
1259 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1260
Dees Troy9d723272014-04-07 17:13:10 +00001261 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001262 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001263 return -1;
1264 }
bigbiffce8f83c2015-12-12 18:30:21 -05001265
Dees Troy9d723272014-04-07 17:13:10 +00001266 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001267 LOGINFO("Error creating pipe\n");
1268 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001269 close(input_fd);
1270 return -1;
1271 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001272
1273 pigz_pid = fork();
1274 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001275 LOGINFO("fork() failed\n");
1276 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001277 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001278 close(pigzfd[0]);
1279 close(pigzfd[1]);
1280 return -1;
1281 } else if (pigz_pid == 0) {
1282 // Child
1283 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001284 dup2(pigzfd[1], 1); // remap stdout
bigbiffce8f83c2015-12-12 18:30:21 -05001285 dup2(input_fd, 0); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001286 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1287 close(pigzfd[1]);
1288 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001289 LOGINFO("execlp openaes ERROR!\n");
1290 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001291 _exit(-1);
1292 }
1293 } else {
1294 // Parent
1295 close(pigzfd[1]); // close parent output
1296 fd = pigzfd[0]; // copy parent input
bigbiffce8f83c2015-12-12 18:30:21 -05001297 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 +00001298 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001299 LOGINFO("tar_fdopen failed\n");
1300 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001301 return -1;
1302 }
1303 }
bigbiffce8f83c2015-12-12 18:30:21 -05001304 } else {
1305 if (part_settings->adbbackup) {
1306 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1307 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
1308 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) {
1309 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1310 gui_err("restore_error=Error during restore process.");
1311 return -1;
1312 }
1313 }
1314 else {
1315 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) {
1316 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1317 gui_err("restore_error=Error during restore process.");
1318 return -1;
1319 }
1320 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001321 }
1322 return 0;
1323}
1324
1325string twrpTar::Strip_Root_Dir(string Path) {
1326 string temp;
1327 size_t slash;
1328
1329 if (Path.substr(0, 1) == "/")
1330 temp = Path.substr(1, Path.size() - 1);
1331 else
1332 temp = Path;
1333 slash = temp.find("/");
1334 if (slash == string::npos)
1335 return temp;
1336 else {
1337 string stripped;
1338
1339 stripped = temp.substr(slash, temp.size() - slash);
1340 return stripped;
1341 }
1342 return temp;
1343}
1344
1345int twrpTar::addFile(string fn, bool include_root) {
1346 char* charTarFile = (char*) fn.c_str();
1347 if (include_root) {
1348 if (tar_append_file(t, charTarFile, NULL) == -1)
1349 return -1;
1350 } else {
1351 string temp = Strip_Root_Dir(fn);
1352 char* charTarPath = (char*) temp.c_str();
1353 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1354 return -1;
1355 }
1356 return 0;
1357}
1358
Dees_Troy83bd4832013-05-04 12:39:56 +00001359int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001360 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001361 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001362 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001363 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001364 tar_close(t);
1365 return -1;
1366 }
1367 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001368 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001369 return -1;
1370 }
bigbiffce8f83c2015-12-12 18:30:21 -05001371 if (current_archive_type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001372 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001373 int status;
1374 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1375 return -1;
1376 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1377 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001378 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001379 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001380 if (!part_settings->adbbackup) {
1381 if (use_compression && !use_encryption) {
1382 string gzname = tarfn + ".gz";
1383 if (TWFunc::Path_Exists(gzname)) {
1384 rename(gzname.c_str(), tarfn.c_str());
1385 }
Dees Troye0a433a2013-12-02 04:10:37 +00001386 }
bigbiffce8f83c2015-12-12 18:30:21 -05001387 if (TWFunc::Get_File_Size(tarfn) == 0) {
1388 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1389 return -1;
1390 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001391#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001392 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001393#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001394 }
1395 else {
1396 if (!twadbbu::Write_TWEOF())
1397 return -1;
1398 }
1399 close(input_fd);
1400 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001401 return 0;
1402}
1403
1404int twrpTar::removeEOT(string tarFile) {
1405 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001406 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001407 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001408 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001409 tar_skip_regfile(t);
1410 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001411 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001412 if (tar_close(t) == -1)
1413 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001414 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001415 return -1;
1416 return 0;
1417}
1418
n0d33b511632013-03-06 21:14:15 +02001419int twrpTar::entryExists(string entry) {
1420 char* searchstr = (char*)entry.c_str();
1421 int ret;
1422
bigbiffce8f83c2015-12-12 18:30:21 -05001423 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001424
Dees_Troy83bd4832013-05-04 12:39:56 +00001425 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001426 ret = 0;
1427 else
1428 ret = tar_find(t, searchstr);
1429
Dees_Troy83bd4832013-05-04 12:39:56 +00001430 if (closeTar() != 0)
1431 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001432
1433 return ret;
1434}
1435
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001436unsigned long long twrpTar::get_size() {
bigbiffce8f83c2015-12-12 18:30:21 -05001437 if (TWFunc::Path_Exists(tarfn) && !part_settings->adbbackup) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001438 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001439 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001440 } else {
1441 LOGINFO("Multiple archives\n");
1442 string temp;
1443 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001444 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001445 unsigned long long total_restore_size = 0;
1446
1447 basefn = tarfn;
1448 temp = basefn + "%i%02i";
1449 tarfn += "000";
1450 thread_id = 0;
1451 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001452 if (!part_settings->adbbackup) {
1453 if (!TWFunc::Path_Exists(actual_filename)) {
1454 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1455 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001456 }
bigbiffce8f83c2015-12-12 18:30:21 -05001457 for (int i = 0; i < 9; i++) {
1458 archive_count = 0;
1459 sprintf(actual_filename, temp.c_str(), i, archive_count);
1460 while (TWFunc::Path_Exists(actual_filename)) {
1461 total_restore_size += uncompressedSize(actual_filename);
1462 archive_count++;
1463 if (archive_count > 99)
1464 break;
1465 sprintf(actual_filename, temp.c_str(), i, archive_count);
1466 }
1467 }
1468 #ifndef BUILD_TWRPTAR_MAIN
1469 if (!part_settings->adbbackup) {
1470 InfoManager backup_info(tarfn + ".info");
1471 backup_info.SetValue("backup_size", total_restore_size);
1472 backup_info.SetValue("backup_type", current_archive_type);
1473 backup_info.SaveValues();
1474 }
1475 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001476 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001477 return total_restore_size;
1478 }
1479 return 0;
1480}
1481
bigbiffce8f83c2015-12-12 18:30:21 -05001482unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001483 unsigned long long total_size = 0;
1484 string Tar, Command, result;
1485 vector<string> split;
1486
bigbiffce8f83c2015-12-12 18:30:21 -05001487 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1488 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001489 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001490 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001491 // Compressed
1492 Command = "pigz -l '" + filename + "'";
1493 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1494 we get the uncompressed size at once. */
1495 TWFunc::Exec_Cmd(Command, result);
1496 if (!result.empty()) {
1497 /* Expected output:
1498 compressed original reduced name
1499 95855838 179403776 -1.3% data.yaffs2.win
1500 ^
1501 split[5]
1502 */
1503 split = TWFunc::split_string(result, ' ', true);
1504 if (split.size() > 4)
1505 total_size = atoi(split[5].c_str());
1506 }
bigbiffce8f83c2015-12-12 18:30:21 -05001507 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001508 // File is encrypted and may be compressed
1509 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001510 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001511 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001512 total_size = TWFunc::Get_File_Size(filename);
1513 } else if (ret == 1) {
1514 LOGERR("Decrypted file is not in tar format.\n");
1515 total_size = TWFunc::Get_File_Size(filename);
1516 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001517 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1518 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1519 we get the uncompressed size at once. */
1520 TWFunc::Exec_Cmd(Command, result);
1521 if (!result.empty()) {
1522 LOGINFO("result was: '%s'\n", result.c_str());
1523 /* Expected output:
1524 compressed original reduced name
1525 95855838 179403776 -1.3% data.yaffs2.win
1526 ^
1527 split[5]
1528 */
1529 split = TWFunc::split_string(result, ' ', true);
1530 if (split.size() > 4)
1531 total_size = atoi(split[5].c_str());
1532 }
1533 } else {
1534 total_size = TWFunc::Get_File_Size(filename);
1535 }
1536 }
1537
1538 return total_size;
1539}
1540
Dees_Troye34c1332013-02-06 19:13:00 +00001541extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1542 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001543}
Ethan Yonker472f5062016-02-25 13:47:30 -06001544
1545extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1546 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1547}