blob: d15eea6b9fe8eb09e98aece506992226ef49e61b [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
Ethan Yonker79f88bd2016-12-09 14:52:12 -060056#ifdef TW_INCLUDE_FBE
57#include "crypto/ext4crypt/ext4crypt_tar.h"
Ethan Yonker8d039f72017-02-03 14:26:15 -060058#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR |TAR_STORE_EXT4_POL
Ethan Yonker79f88bd2016-12-09 14:52:12 -060059#else
Ethan Yonker8d039f72017-02-03 14:26:15 -060060#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR
Ethan Yonker79f88bd2016-12-09 14:52:12 -060061#endif
62
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063using namespace std;
64
Dees_Troy83bd4832013-05-04 12:39:56 +000065twrpTar::twrpTar(void) {
66 use_encryption = 0;
67 userdata_encryption = 0;
68 use_compression = 0;
69 split_archives = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +000070 pigz_pid = 0;
71 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000072 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060073 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000074 include_root_dir = true;
Ethan Yonkerf1179622016-08-25 15:32:21 -050075 tar_type.openfunc = open;
76 tar_type.closefunc = close;
77 tar_type.readfunc = read;
Ethan Yonkerea2fcf02016-09-12 16:07:19 -050078 input_fd = -1;
79 output_fd = -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -060080 backup_exclusions = NULL;
Ethan Yonker79f88bd2016-12-09 14:52:12 -060081#ifdef TW_INCLUDE_FBE
82 e4crypt_set_mode();
83#endif
Dees_Troy83bd4832013-05-04 12:39:56 +000084}
85
86twrpTar::~twrpTar(void) {
87 // Do nothing
88}
89
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050090void twrpTar::setfn(string fn) {
91 tarfn = fn;
92}
93
94void twrpTar::setdir(string dir) {
95 tardir = dir;
96}
97
Dees Troye0a433a2013-12-02 04:10:37 +000098void twrpTar::setsize(unsigned long long backup_size) {
99 Total_Backup_Size = backup_size;
100}
101
Ethan Yonker87af5632014-02-10 11:56:35 -0600102void twrpTar::setpassword(string pass) {
103 password = pass;
104}
105
bigbiff7abc5fe2015-01-17 16:53:12 -0500106void twrpTar::Signal_Kill(int signum) {
107 _exit(255);
108}
109
bigbiffce8f83c2015-12-12 18:30:21 -0500110void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
111 current_archive_type = archive_type;
112}
113
114int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000115 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600116 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500117
118 file_count = 0;
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600119 if (backup_exclusions == NULL) {
120 LOGINFO("backup_exclusions is NULL\n");
121 return -1;
122 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500123
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600124#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500125 if (part_settings->adbbackup) {
126 std::string Backup_FileName(tarfn);
127 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
128 return -1;
129 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600130#endif
bigbiffce8f83c2015-12-12 18:30:21 -0500131
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500132 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500133 LOGINFO("Error creating progress tracking pipe\n");
134 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500135 return -1;
136 }
bigbiffce8f83c2015-12-12 18:30:21 -0500137 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000138 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500139 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500140 close(progress_pipe[0]);
141 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500142 return -1;
143 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500144
bigbiffce8f83c2015-12-12 18:30:21 -0500145 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500146 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500147 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500148 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500149 close(progress_pipe[0]);
150 progress_pipe_fd = progress_pipe[1];
151
Dees_Troy83bd4832013-05-04 12:39:56 +0000152 if (use_encryption || userdata_encryption) {
153 LOGINFO("Using encryption\n");
154 DIR* d;
155 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200156 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
157 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000158 int item_len, ret, thread_error = 0;
159 std::vector<TarListStruct> RegularList;
160 std::vector<TarListStruct> EncryptList;
161 string FileName;
162 struct TarListStruct TarItem;
163 twrpTar reg, enc[9];
164 struct stat st;
165 pthread_t enc_thread[9];
166 pthread_attr_t tattr;
167 void *thread_return;
168
169 core_count = sysconf(_SC_NPROCESSORS_CONF);
170 if (core_count > 8)
171 core_count = 8;
that2252d242015-04-03 22:33:04 +0200172 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000173 Archive_Current_Size = 0;
174
175 d = opendir(tardir.c_str());
176 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500177 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500178 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000179 _exit(-1);
180 }
181 // Figure out the size of all data to be encrypted and create a list of unencrypted files
182 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500183 FileName = tardir + "/" + de->d_name;
184
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600185 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000186 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500187 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000188 item_len = strlen(de->d_name);
189 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 -0500190 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
191 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500192 LOGINFO("Error in Generate_TarList with regular list!\n");
193 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000194 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500195 close(progress_pipe_fd);
196 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000197 _exit(-1);
198 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500199 file_count = (unsigned long long)(ret);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600200 regular_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000201 } else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600202 encrypt_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000203 }
204 } else if (de->d_type == DT_REG) {
205 stat(FileName.c_str(), &st);
206 encrypt_size += (unsigned long long)(st.st_size);
207 }
208 }
209 closedir(d);
210
211 target_size = encrypt_size / core_count;
212 target_size++;
213 LOGINFO(" Unencrypted size: %llu\n", regular_size);
214 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
215 LOGINFO(" Target size : %llu\n", target_size);
216 if (!userdata_encryption) {
217 enc_thread_id = 0;
218 start_thread_id = 0;
219 core_count--;
220 }
221 Archive_Current_Size = 0;
222
223 d = opendir(tardir.c_str());
224 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500225 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500226 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000227 _exit(-1);
228 }
229 // Divide up the encrypted file list for threading
230 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500231 FileName = tardir + "/" + de->d_name;
232
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600233 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000234 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500235 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000236 item_len = strlen(de->d_name);
237 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
238 // Do nothing, we added these to RegularList earlier
239 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500240 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500241 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
242 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500243 LOGINFO("Error in Generate_TarList with encrypted list!\n");
244 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000245 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500246 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000247 _exit(-1);
248 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500249 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000250 }
251 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
252 stat(FileName.c_str(), &st);
253 if (de->d_type == DT_REG)
254 Archive_Current_Size += (unsigned long long)(st.st_size);
255 TarItem.fn = FileName;
256 TarItem.thread_id = enc_thread_id;
257 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500258 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000259 }
260 }
261 closedir(d);
262 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500263 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 -0500264 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500265 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500266 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000267 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500268 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500269 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500270 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000271 }
272
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500273 // Send file count to parent
274 write(progress_pipe_fd, &file_count, sizeof(file_count));
275 // Send backup size to parent
276 total_size = regular_size + encrypt_size;
277 write(progress_pipe_fd, &total_size, sizeof(total_size));
278
Dees_Troy83bd4832013-05-04 12:39:56 +0000279 if (userdata_encryption) {
280 // Create a backup of unencrypted data
281 reg.setfn(tarfn);
282 reg.ItemList = &RegularList;
283 reg.thread_id = 0;
284 reg.use_encryption = 0;
285 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000286 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500287 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500288 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000289 LOGINFO("Creating unencrypted backup...\n");
290 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500291 LOGINFO("Error creating unencrypted backup.\n");
292 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500293 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000294 _exit(-1);
295 }
296 }
297
298 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500299 LOGINFO("Unable to pthread_attr_init\n");
300 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500301 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000302 _exit(-1);
303 }
304 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500305 LOGINFO("Error setting pthread_attr_setdetachstate\n");
306 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500307 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000308 _exit(-1);
309 }
310 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500311 LOGINFO("Error setting pthread_attr_setscope\n");
312 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500313 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000314 _exit(-1);
315 }
316 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
317 LOGERR("Error setting pthread_attr_setstacksize\n");
318 _exit(-1);
319 }*/
320
321 // Create threads for the divided up encryption lists
322 for (i = start_thread_id; i <= core_count; i++) {
323 enc[i].setdir(tardir);
324 enc[i].setfn(tarfn);
325 enc[i].ItemList = &EncryptList;
326 enc[i].thread_id = i;
327 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500328 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000329 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000330 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500331 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500332 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000333 LOGINFO("Start encryption thread %i\n", i);
334 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
335 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500336 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 +0000337 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500338 LOGINFO("Error creating encrypted backup %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 enc[i].thread_id = i + 1;
344 }
345 }
346 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
347 }
348 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500349 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000350 }
351 for (i = start_thread_id; i <= core_count; i++) {
352 if (enc[i].thread_id == i) {
353 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500354 LOGINFO("Error joining thread %i\n", i);
355 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500356 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000357 _exit(-1);
358 } else {
359 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200360 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000361 if (ret != 0) {
362 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500363 LOGINFO("Thread %i returned an error %i.\n", i, ret);
364 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500365 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000366 _exit(-1);
367 }
368 }
369 } else {
370 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
371 }
372 }
373 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500374 LOGINFO("Error returned by one or more threads.\n");
375 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500376 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000377 _exit(-1);
378 }
379 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500380 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000381 _exit(0);
382 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500383 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000384 std::vector<TarListStruct> FileList;
385 unsigned thread_id = 0;
386 unsigned long long target_size = 0;
387 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500388 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000389
390 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500391 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
392 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500393 LOGINFO("Error in Generate_TarList!\n");
394 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500395 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000396 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000397 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500398 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000399 // Create a backup
400 reg.setfn(tarfn);
401 reg.ItemList = &FileList;
402 reg.thread_id = 0;
403 reg.use_encryption = 0;
404 reg.use_compression = use_compression;
405 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500406 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500407 reg.part_settings = part_settings;
408 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500409 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000410 reg.split_archives = 1;
411 } else {
412 reg.split_archives = 0;
413 }
414 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500415 write(progress_pipe_fd, &file_count, sizeof(file_count));
416 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000417 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500418 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500419 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000420 _exit(-1);
421 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500422 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000423 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000424 }
425 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500426 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600427 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500428 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500429
430 // Parent closes output side
431 close(progress_pipe[1]);
432
433 // Read progress data from children
434 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
435 if (first_data == 0) {
436 // First incoming data is the file count
437 file_count = fs;
438 if (file_count == 0) file_count = 1; // prevent division by 0 below
439 first_data = 1;
440 } else if (first_data == 1) {
441 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500442 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500443 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500444 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600445 if (fs > 0) {
446 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500447 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600448 } else { // fs == 0 increments the file counter
449 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500450 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600451 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500452 }
453 }
454 close(progress_pipe[0]);
455#ifndef BUILD_TWRPTAR_MAIN
456 DataManager::SetValue("tw_file_progress", "");
457 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500458 part_settings->progress->DisplayFileCount(false);
459 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500460
bigbiffce8f83c2015-12-12 18:30:21 -0500461 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400462 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500463 backup_info.SetValue("backup_size", size_backup);
464 if (use_compression && use_encryption)
465 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
466 else if (use_encryption)
467 backup_info.SetValue("backup_type", ENCRYPTED);
468 else if (use_compression)
469 backup_info.SetValue("backup_type", COMPRESSED);
470 else
471 backup_info.SetValue("backup_type", UNCOMPRESSED);
472 backup_info.SetValue("file_count", files_backup);
473 backup_info.SaveValues();
474 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500475#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500476 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500477 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500478 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500479 return 0;
480}
481
bigbiffce8f83c2015-12-12 18:30:21 -0500482int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000483 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600484 pid_t tar_fork_pid;
485 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500486
487 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500488 LOGINFO("Error creating progress tracking pipe\n");
489 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500490 return -1;
491 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000492
bigbiff7abc5fe2015-01-17 16:53:12 -0500493 tar_fork_pid = fork();
494 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000495 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500496 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000497 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500498 close(progress_pipe[0]);
499 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500500 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000501 LOGINFO("Single archive\n");
502 if (extract() != 0)
503 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500504 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000505 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500506 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000507 } else {
508 LOGINFO("Multiple archives\n");
509 string temp;
510 char actual_filename[255];
511 twrpTar tars[9];
512 pthread_t tar_thread[9];
513 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500514 unsigned thread_count = 0, i, start_thread_id = 1;
515 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000516 void *thread_return;
517
518 basefn = tarfn;
519 temp = basefn + "%i%02i";
520 tarfn += "000";
521 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500522 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
523 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500524 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000525 _exit(-1);
526 }
527 if (TWFunc::Get_File_Type(tarfn) != 2) {
528 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
529 tars[0].basefn = basefn;
530 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500531 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500532 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500534 LOGINFO("Error extracting split archive.\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 } else {
540 start_thread_id = 0;
541 }
542 // Start threading encrypted restores
543 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500544 LOGINFO("Unable to pthread_attr_init\n");
545 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500546 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000547 _exit(-1);
548 }
549 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500550 LOGINFO("Error setting pthread_attr_setdetachstate\n");
551 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500552 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000553 _exit(-1);
554 }
555 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500556 LOGINFO("Error setting pthread_attr_setscope\n");
557 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500558 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000559 _exit(-1);
560 }
561 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
562 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500563 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000564 _exit(-1);
565 }*/
566 for (i = start_thread_id; i < 9; i++) {
567 sprintf(actual_filename, temp.c_str(), i, 0);
568 if (TWFunc::Path_Exists(actual_filename)) {
569 thread_count++;
570 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500571 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000572 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500573 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500574 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000575 LOGINFO("Creating extract thread ID %i\n", i);
576 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
577 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500578 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 +0000579 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500580 LOGINFO("Error extracting backup in 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 tars[i].thread_id = i + 1;
586 }
587 }
588 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
589 } else {
590 break;
591 }
592 }
593 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
594 if (tars[i].thread_id == i) {
595 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500596 LOGINFO("Error joining thread %i\n", i);
597 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500598 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000599 _exit(-1);
600 } else {
601 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200602 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000603 if (ret != 0) {
604 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500605 LOGINFO("Thread %i returned an error %i.\n", i, ret);
606 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500607 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000608 _exit(-1);
609 }
610 }
611 } else {
612 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
613 }
614 }
615 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500616 LOGINFO("Error returned by one or more threads.\n");
617 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500618 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000619 _exit(-1);
620 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500621 LOGINFO("Finished encrypted restore.\n");
622 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000623 _exit(0);
624 }
625 }
626 else // parent process
627 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600628 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500629
630 // Parent closes output side
631 close(progress_pipe[1]);
632
633 // Read progress data from children
634 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
635 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500636 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500637 }
638 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500639 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500640
bigbiff7abc5fe2015-01-17 16:53:12 -0500641 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000642 return -1;
643 }
644 }
645 else // fork has failed
646 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500647 close(progress_pipe[0]);
648 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000649 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500650 return -1;
651 }
652 return 0;
653}
654
Dees_Troy83bd4832013-05-04 12:39:56 +0000655int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
656 DIR* d;
657 struct dirent* de;
658 struct stat st;
659 string FileName;
660 struct TarListStruct TarItem;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500661 int ret, file_count;
662 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000663
Dees_Troy83bd4832013-05-04 12:39:56 +0000664 d = opendir(Path.c_str());
665 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500666 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000667 closedir(d);
668 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500669 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000670 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500671 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500672
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600673 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000674 continue;
675 TarItem.fn = FileName;
676 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500677 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000678 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500679 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
680 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500681 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500682 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000683 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
684 stat(FileName.c_str(), &st);
685 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500686 if (de->d_type == DT_REG) {
687 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000688 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500689 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000690 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
691 *thread_id = *thread_id + 1;
692 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500693 }
694 }
695 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000696 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500697 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500698}
699
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500700int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000701 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000702 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500703 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500704 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500705 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
706 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500707 return -1;
708 }
709 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500710 LOGINFO("Unable to close tar file\n");
711 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500712 return -1;
713 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600714#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500715 if (part_settings->adbbackup) {
716 if (!twadbbu::Write_TWEOF())
717 return -1;
718 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600719#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500720 return 0;
721}
722
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500723int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500724 if (!part_settings->adbbackup) {
725 LOGINFO("Setting archive type\n");
726 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
727 }
728 else {
729 if (part_settings->adb_compression == 1)
730 current_archive_type = COMPRESSED;
731 else
732 current_archive_type = UNCOMPRESSED;
733 }
n0d33b511632013-03-06 21:14:15 +0200734
bigbiffce8f83c2015-12-12 18:30:21 -0500735 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500736 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000737 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000738 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500739 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500740 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600741 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000742 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500743 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000744 return -1;
745 }
746 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500747 LOGINFO("Decrypted file is not in tar format.\n");
748 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000749 return -1;
750 }
751 if (ret == 3) {
752 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500753 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000754 } else
755 LOGINFO("Extracting encrypted tar.\n");
756 return extractTar();
757 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000758 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500759 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500760 }
761}
762
Dees Troye0a433a2013-12-02 04:10:37 +0000763int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000764 struct stat st;
765 char buf[PATH_MAX];
766 int list_size = TarList->size(), i = 0, archive_count = 0;
767 string temp;
768 char actual_filename[PATH_MAX];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500769 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000770
Dees Troye0a433a2013-12-02 04:10:37 +0000771 if (split_archives) {
772 basefn = tarfn;
773 temp = basefn + "%i%02i";
774 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
775 tarfn = actual_filename;
776 include_root_dir = true;
777 } else {
778 include_root_dir = false;
779 }
bigbiffce8f83c2015-12-12 18:30:21 -0500780
781 if (part_settings->adbbackup)
782 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
783 else
784 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
785
Dees_Troy83bd4832013-05-04 12:39:56 +0000786 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500787 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
788 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000789 return -2;
790 }
791 Archive_Current_Size = 0;
792
793 while (i < list_size) {
794 if (TarList->at(i).thread_id == thread_id) {
795 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400796 lstat(buf, &st);
797 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500798 fs = (unsigned long long)(st.st_size);
799 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000800 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500801 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
802 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000803 return -3;
804 }
805 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500806 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000807 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500808 LOGINFO("Too many archives for thread %i\n", thread_id);
809 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000810 return -4;
811 }
812 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
813 tarfn = actual_filename;
814 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500815 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
816 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000817 return -2;
818 }
819 Archive_Current_Size = 0;
820 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500821 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600822 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500823 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000824 }
Dees Troye0a433a2013-12-02 04:10:37 +0000825 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
826 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500827 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
828 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000829 return -1;
830 }
831 }
832 i++;
833 }
834 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500835 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
836 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000837 return -3;
838 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600839 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000840 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500841}
842
Dees_Troy83bd4832013-05-04 12:39:56 +0000843void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000844 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600845 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000846 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
847 return (void*)-2;
848 }
849 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
850 return (void*)0;
851}
852
853void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000854 twrpTar* threadTar = (twrpTar*) cookie;
855 int archive_count = 0;
856 string temp = threadTar->basefn + "%i%02i";
857 char actual_filename[255];
858 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
859 while (TWFunc::Path_Exists(actual_filename)) {
860 threadTar->tarfn = actual_filename;
861 if (threadTar->extract() != 0) {
862 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
863 return (void*)-2;
864 }
865 archive_count++;
866 if (archive_count > 99)
867 break;
868 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
869 }
870 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
871 return (void*)0;
872}
873
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500874int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
875 char* charTarFile = (char*) fn.c_str();
876
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600877 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500878 return -1;
879 removeEOT(charTarFile);
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600880 if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500881 return -1;
882 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500883 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500884 if (tar_append_file(t, file, file) == -1)
885 return -1;
886 }
887 if (tar_append_eof(t) == -1)
888 return -1;
889 if (tar_close(t) == -1)
890 return -1;
891 return 0;
892}
893
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500894int twrpTar::createTar() {
895 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000896 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500897
Dees_Troy83bd4832013-05-04 12:39:56 +0000898 if (use_encryption && use_compression) {
899 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500900 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000901 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000902 int i, pipes[4];
903
904 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500905 LOGINFO("Error creating first pipe\n");
906 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500907 return -1;
908 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000909 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500910 LOGINFO("Error creating second pipe\n");
911 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500912 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000913 }
bigbiffce8f83c2015-12-12 18:30:21 -0500914 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 +0000915 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500916 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000917 for (i = 0; i < 4; i++)
918 close(pipes[i]); // close all
919 return -1;
920 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000921 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400922
Dees_Troy83bd4832013-05-04 12:39:56 +0000923 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500924 LOGINFO("pigz fork() failed\n");
925 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000926 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000927 for (i = 0; i < 4; i++)
928 close(pipes[i]); // close all
929 return -1;
930 } else if (pigz_pid == 0) {
931 // pigz Child
932 close(pipes[1]);
933 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500934 int stdinfd = fileno(stdin);
935 int stdoutfd = fileno(stdout);
936 close(stdinfd);
937 dup2(pipes[0], stdinfd);
938 close(stdoutfd);
939 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000940 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500941 LOGINFO("execlp pigz ERROR!\n");
942 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000943 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000944 close(pipes[0]);
945 close(pipes[3]);
946 _exit(-1);
947 }
948 } else {
949 // Parent
950 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400951
Dees_Troy83bd4832013-05-04 12:39:56 +0000952 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500953 LOGINFO("openaes fork() failed\n");
954 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000955 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000956 for (i = 0; i < 4; i++)
957 close(pipes[i]); // close all
958 return -1;
959 } else if (oaes_pid == 0) {
960 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000961 close(pipes[0]);
962 close(pipes[1]);
963 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500964 int stdinfd = fileno(stdin);
965 int stdoutfd = fileno(stdout);
966 close(stdinfd);
967 dup2(pipes[2], stdinfd);
968 close(stdoutfd);
969 dup2(output_fd, stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -0600970 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500971 LOGINFO("execlp openaes ERROR!\n");
972 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000973 close(pipes[2]);
974 close(output_fd);
975 _exit(-1);
976 }
977 } else {
978 // Parent
979 close(pipes[0]);
980 close(pipes[2]);
981 close(pipes[3]);
982 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600983 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500984 tar_type.writefunc = write_tar_no_buffer;
Matt Mowera8a89d12016-12-30 18:10:37 -0600985 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, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000986 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500987 LOGINFO("tar_fdopen failed\n");
988 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000989 return -1;
990 }
991 return 0;
992 }
993 }
994 } else if (use_compression) {
995 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500996 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000997 LOGINFO("Using compression...\n");
998 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500999 if (part_settings->adbbackup) {
1000 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
1001 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1002 }
1003 else {
1004 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);
1005 }
Dees Troy9d723272014-04-07 17:13:10 +00001006 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001007 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001008 close(pigzfd[0]);
1009 return -1;
1010 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001011
1012 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001013 LOGINFO("Error creating pipe\n");
1014 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001015 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001016 return -1;
1017 }
1018 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001019
Dees_Troy83bd4832013-05-04 12:39:56 +00001020 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001021 LOGINFO("fork() failed\n");
1022 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001023 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001024 close(pigzfd[0]);
1025 close(pigzfd[1]);
1026 return -1;
1027 } else if (pigz_pid == 0) {
1028 // Child
1029 close(pigzfd[1]); // close unused output pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001030 dup2(pigzfd[0], fileno(stdin)); // remap stdin
1031 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001032 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001033 LOGINFO("execlp pigz ERROR!\n");
1034 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001035 close(output_fd);
1036 close(pigzfd[0]);
1037 _exit(-1);
1038 }
1039 } else {
1040 // Parent
1041 close(pigzfd[0]); // close parent input
1042 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001043 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001044 tar_type.writefunc = write_tar_no_buffer;
Matt Mowera8a89d12016-12-30 18:10:37 -06001045 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, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001046 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001047 LOGINFO("tar_fdopen failed\n");
1048 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001049 return -1;
1050 }
1051 }
1052 } else if (use_encryption) {
1053 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001054 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001055 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001056 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001057 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 +00001058 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001059 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001060 return -1;
1061 }
1062 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001063 LOGINFO("Error creating pipe\n");
1064 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001065 close(output_fd);
1066 return -1;
1067 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001068 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001069
Dees_Troy83bd4832013-05-04 12:39:56 +00001070 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001071 LOGINFO("fork() failed\n");
1072 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001073 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001074 close(oaesfd[0]);
1075 close(oaesfd[1]);
1076 return -1;
1077 } else if (oaes_pid == 0) {
1078 // Child
1079 close(oaesfd[1]); // close unused
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001080 dup2(oaesfd[0], fileno(stdin)); // remap stdin
1081 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001082 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001083 LOGINFO("execlp openaes ERROR!\n");
1084 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001085 close(output_fd);
1086 close(oaesfd[0]);
1087 _exit(-1);
1088 }
1089 } else {
1090 // Parent
1091 close(oaesfd[0]); // close parent input
1092 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001093 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001094 tar_type.writefunc = write_tar_no_buffer;
Matt Mowera8a89d12016-12-30 18:10:37 -06001095 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, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001096 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001097 LOGINFO("tar_fdopen failed\n");
1098 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001099 return -1;
1100 }
1101 return 0;
1102 }
1103 } else {
1104 // Not compressed or encrypted
nkk71d59d02e2017-06-29 15:16:23 +03001105 current_archive_type = UNCOMPRESSED;
Ethan Yonker472f5062016-02-25 13:47:30 -06001106 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001107 if (part_settings->adbbackup) {
1108 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001109 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001110 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001111 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, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001112 close(output_fd);
1113 LOGERR("tar_fdopen failed\n");
1114 return -1;
1115 }
1116 }
1117 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001118 tar_type.writefunc = write_tar;
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001119 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, TWTAR_FLAGS) == -1) {
bigbiffce8f83c2015-12-12 18:30:21 -05001120 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1121 gui_err("backup_error=Error creating backup.");
1122 return -1;
1123 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001124 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001125 }
1126 return 0;
1127}
1128
Dees_Troy83bd4832013-05-04 12:39:56 +00001129int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001130 char* charRootDir = (char*) tardir.c_str();
1131 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001132 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001133
bigbiffce8f83c2015-12-12 18:30:21 -05001134 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001135 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001136 int i, pipes[4];
bigbiffce8f83c2015-12-12 18:30:21 -05001137 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001138 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001139 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001140 return -1;
1141 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001142
1143 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001144 LOGINFO("Error creating first pipe\n");
1145 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001146 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001147 return -1;
1148 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001149 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001150 LOGINFO("Error creating second pipe\n");
1151 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001152 close(pipes[0]);
1153 close(pipes[1]);
1154 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001155 return -1;
1156 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001157 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001158
Dees_Troy83bd4832013-05-04 12:39:56 +00001159 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001160 LOGINFO("pigz fork() failed\n");
1161 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001162 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001163 for (i = 0; i < 4; i++)
1164 close(pipes[i]); // close all
1165 return -1;
1166 } else if (oaes_pid == 0) {
1167 // openaes Child
1168 close(pipes[0]); // Close pipes that are not used by this child
1169 close(pipes[2]);
1170 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001171 int stdinfd = fileno(stdin);
1172 int stdoutfd = fileno(stdout);
1173 close(stdinfd);
1174 dup2(input_fd, stdinfd);
1175 close(stdoutfd);
1176 dup2(pipes[1], stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -06001177 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001178 LOGINFO("execlp openaes ERROR!\n");
1179 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001180 close(input_fd);
1181 close(pipes[1]);
1182 _exit(-1);
1183 }
1184 } else {
1185 // Parent
1186 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001187
Dees_Troy83bd4832013-05-04 12:39:56 +00001188 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001189 LOGINFO("openaes fork() failed\n");
1190 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001191 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001192 for (i = 0; i < 4; i++)
1193 close(pipes[i]); // close all
1194 return -1;
1195 } else if (pigz_pid == 0) {
1196 // pigz Child
1197 close(pipes[1]); // Close pipes not used by this child
1198 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001199 int stdinfd = fileno(stdin);
1200 int stdoutfd = fileno(stdout);
1201 close(stdinfd);
1202 dup2(pipes[0], stdinfd);
1203 close(stdoutfd);
1204 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001205 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001206 LOGINFO("execlp pigz ERROR!\n");
1207 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001208 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001209 close(pipes[0]);
1210 close(pipes[3]);
1211 _exit(-1);
1212 }
1213 } else {
1214 // Parent
1215 close(pipes[0]); // Close pipes not used by parent
1216 close(pipes[1]);
1217 close(pipes[3]);
1218 fd = pipes[2];
Matt Mowera8a89d12016-12-30 18:10:37 -06001219 if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001220 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001221 LOGINFO("tar_fdopen failed\n");
1222 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001223 return -1;
1224 }
1225 }
1226 }
bigbiffce8f83c2015-12-12 18:30:21 -05001227 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001228 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001229 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001230 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001231 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001232 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001233 return -1;
1234 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001235
Dees Troy9d723272014-04-07 17:13:10 +00001236 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001237 LOGINFO("Error creating pipe\n");
1238 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001239 close(input_fd);
1240 return -1;
1241 }
1242
Dees_Troy83bd4832013-05-04 12:39:56 +00001243 oaes_pid = fork();
1244 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001245 LOGINFO("fork() failed\n");
1246 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001247 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001248 close(oaesfd[0]);
1249 close(oaesfd[1]);
1250 return -1;
1251 } else if (oaes_pid == 0) {
1252 // Child
1253 close(oaesfd[0]); // Close unused pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001254 int stdinfd = fileno(stdin);
1255 close(stdinfd); // close stdin
1256 dup2(oaesfd[1], fileno(stdout)); // remap stdout
1257 dup2(input_fd, stdinfd); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001258 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001259 LOGINFO("execlp openaes ERROR!\n");
1260 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001261 close(input_fd);
1262 close(oaesfd[1]);
1263 _exit(-1);
1264 }
1265 } else {
1266 // Parent
1267 close(oaesfd[1]); // close parent output
1268 fd = oaesfd[0]; // copy parent input
Matt Mowera8a89d12016-12-30 18:10:37 -06001269 if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001270 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001271 LOGINFO("tar_fdopen failed\n");
1272 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001273 return -1;
1274 }
1275 }
bigbiffce8f83c2015-12-12 18:30:21 -05001276 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001277 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001278
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -04001279 LOGINFO("Opening gzip compressed tar...\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001280 if (part_settings->adbbackup) {
1281 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
1282 input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE);
1283 }
1284 else
1285 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1286
Dees Troy9d723272014-04-07 17:13:10 +00001287 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001288 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001289 return -1;
1290 }
bigbiffce8f83c2015-12-12 18:30:21 -05001291
Dees Troy9d723272014-04-07 17:13:10 +00001292 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001293 LOGINFO("Error creating pipe\n");
1294 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001295 close(input_fd);
1296 return -1;
1297 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001298
1299 pigz_pid = fork();
1300 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001301 LOGINFO("fork() failed\n");
1302 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001303 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001304 close(pigzfd[0]);
1305 close(pigzfd[1]);
1306 return -1;
1307 } else if (pigz_pid == 0) {
1308 // Child
1309 close(pigzfd[0]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001310 dup2(pigzfd[1], fileno(stdout)); // remap stdout
1311 dup2(input_fd, fileno(stdin)); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001312 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1313 close(pigzfd[1]);
1314 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001315 LOGINFO("execlp openaes ERROR!\n");
1316 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001317 _exit(-1);
1318 }
1319 } else {
1320 // Parent
1321 close(pigzfd[1]); // close parent output
1322 fd = pigzfd[0]; // copy parent input
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001323 if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001324 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001325 LOGINFO("tar_fdopen failed\n");
1326 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001327 return -1;
1328 }
1329 }
bigbiffce8f83c2015-12-12 18:30:21 -05001330 } else {
1331 if (part_settings->adbbackup) {
1332 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1333 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001334 if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001335 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1336 gui_err("restore_error=Error during restore process.");
1337 return -1;
1338 }
1339 }
1340 else {
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001341 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001342 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1343 gui_err("restore_error=Error during restore process.");
1344 return -1;
1345 }
1346 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001347 }
1348 return 0;
1349}
1350
1351string twrpTar::Strip_Root_Dir(string Path) {
1352 string temp;
1353 size_t slash;
1354
1355 if (Path.substr(0, 1) == "/")
1356 temp = Path.substr(1, Path.size() - 1);
1357 else
1358 temp = Path;
1359 slash = temp.find("/");
1360 if (slash == string::npos)
1361 return temp;
1362 else {
1363 string stripped;
1364
1365 stripped = temp.substr(slash, temp.size() - slash);
1366 return stripped;
1367 }
1368 return temp;
1369}
1370
1371int twrpTar::addFile(string fn, bool include_root) {
1372 char* charTarFile = (char*) fn.c_str();
1373 if (include_root) {
1374 if (tar_append_file(t, charTarFile, NULL) == -1)
1375 return -1;
1376 } else {
1377 string temp = Strip_Root_Dir(fn);
1378 char* charTarPath = (char*) temp.c_str();
1379 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1380 return -1;
1381 }
1382 return 0;
1383}
1384
Dees_Troy83bd4832013-05-04 12:39:56 +00001385int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001386 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001387 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001388 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001389 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001390 tar_close(t);
1391 return -1;
1392 }
1393 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001394 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001395 return -1;
1396 }
bigbiffce8f83c2015-12-12 18:30:21 -05001397 if (current_archive_type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001398 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001399 int status;
1400 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1401 return -1;
1402 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1403 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001404 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001405 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001406 if (!part_settings->adbbackup) {
1407 if (use_compression && !use_encryption) {
1408 string gzname = tarfn + ".gz";
1409 if (TWFunc::Path_Exists(gzname)) {
1410 rename(gzname.c_str(), tarfn.c_str());
1411 }
Dees Troye0a433a2013-12-02 04:10:37 +00001412 }
bigbiffce8f83c2015-12-12 18:30:21 -05001413 if (TWFunc::Get_File_Size(tarfn) == 0) {
1414 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1415 return -1;
1416 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001417#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001418 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001419#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001420 }
1421 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001422#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001423 if (!twadbbu::Write_TWEOF())
1424 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001425#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001426 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001427 if (input_fd >= 0)
1428 close(input_fd);
1429 if (output_fd >= 0)
1430 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001431 return 0;
1432}
1433
1434int twrpTar::removeEOT(string tarFile) {
1435 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001436 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001437 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001438 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001439 tar_skip_regfile(t);
1440 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001441 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001442 if (tar_close(t) == -1)
1443 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001444 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001445 return -1;
1446 return 0;
1447}
1448
n0d33b511632013-03-06 21:14:15 +02001449int twrpTar::entryExists(string entry) {
1450 char* searchstr = (char*)entry.c_str();
1451 int ret;
1452
bigbiffce8f83c2015-12-12 18:30:21 -05001453 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001454
Dees_Troy83bd4832013-05-04 12:39:56 +00001455 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001456 ret = 0;
1457 else
1458 ret = tar_find(t, searchstr);
1459
Dees_Troy83bd4832013-05-04 12:39:56 +00001460 if (closeTar() != 0)
1461 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001462
1463 return ret;
1464}
1465
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001466unsigned long long twrpTar::get_size() {
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04001467 if (part_settings->adbbackup || TWFunc::Path_Exists(tarfn)) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001468 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001469 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001470 } else {
1471 LOGINFO("Multiple archives\n");
1472 string temp;
1473 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001474 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001475 unsigned long long total_restore_size = 0;
1476
1477 basefn = tarfn;
1478 temp = basefn + "%i%02i";
1479 tarfn += "000";
1480 thread_id = 0;
1481 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001482 if (!part_settings->adbbackup) {
1483 if (!TWFunc::Path_Exists(actual_filename)) {
1484 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1485 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001486 }
bigbiffce8f83c2015-12-12 18:30:21 -05001487 for (int i = 0; i < 9; i++) {
1488 archive_count = 0;
1489 sprintf(actual_filename, temp.c_str(), i, archive_count);
1490 while (TWFunc::Path_Exists(actual_filename)) {
1491 total_restore_size += uncompressedSize(actual_filename);
1492 archive_count++;
1493 if (archive_count > 99)
1494 break;
1495 sprintf(actual_filename, temp.c_str(), i, archive_count);
1496 }
1497 }
1498 #ifndef BUILD_TWRPTAR_MAIN
1499 if (!part_settings->adbbackup) {
1500 InfoManager backup_info(tarfn + ".info");
1501 backup_info.SetValue("backup_size", total_restore_size);
1502 backup_info.SetValue("backup_type", current_archive_type);
1503 backup_info.SaveValues();
1504 }
1505 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001506 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001507 return total_restore_size;
1508 }
1509 return 0;
1510}
1511
bigbiffce8f83c2015-12-12 18:30:21 -05001512unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001513 unsigned long long total_size = 0;
1514 string Tar, Command, result;
1515 vector<string> split;
1516
bigbiffce8f83c2015-12-12 18:30:21 -05001517 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1518 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001519 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001520 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001521 // Compressed
1522 Command = "pigz -l '" + filename + "'";
1523 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1524 we get the uncompressed size at once. */
1525 TWFunc::Exec_Cmd(Command, result);
1526 if (!result.empty()) {
1527 /* Expected output:
1528 compressed original reduced name
1529 95855838 179403776 -1.3% data.yaffs2.win
1530 ^
1531 split[5]
1532 */
1533 split = TWFunc::split_string(result, ' ', true);
1534 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001535 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001536 }
bigbiffce8f83c2015-12-12 18:30:21 -05001537 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001538 // File is encrypted and may be compressed
1539 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001540 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001541 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001542 total_size = TWFunc::Get_File_Size(filename);
1543 } else if (ret == 1) {
1544 LOGERR("Decrypted file is not in tar format.\n");
1545 total_size = TWFunc::Get_File_Size(filename);
1546 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001547 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1548 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1549 we get the uncompressed size at once. */
1550 TWFunc::Exec_Cmd(Command, result);
1551 if (!result.empty()) {
1552 LOGINFO("result was: '%s'\n", result.c_str());
1553 /* Expected output:
1554 compressed original reduced name
1555 95855838 179403776 -1.3% data.yaffs2.win
1556 ^
1557 split[5]
1558 */
1559 split = TWFunc::split_string(result, ' ', true);
1560 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001561 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001562 }
1563 } else {
1564 total_size = TWFunc::Get_File_Size(filename);
1565 }
1566 }
1567
1568 return total_size;
1569}
1570
Dees_Troye34c1332013-02-06 19:13:00 +00001571extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1572 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001573}
Ethan Yonker472f5062016-02-25 13:47:30 -06001574
1575extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1576 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1577}