blob: 94667a5b4aaa5e58d0a2d754486fa04fc3ad3d71 [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");
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100318 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 _exit(-1);
320 }*/
321
322 // Create threads for the divided up encryption lists
323 for (i = start_thread_id; i <= core_count; i++) {
324 enc[i].setdir(tardir);
325 enc[i].setfn(tarfn);
326 enc[i].ItemList = &EncryptList;
327 enc[i].thread_id = i;
328 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500329 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000330 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000331 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500332 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500333 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000334 LOGINFO("Start encryption thread %i\n", i);
335 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
336 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500337 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 +0000338 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500339 LOGINFO("Error creating encrypted backup %i.\n", i);
340 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500341 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000342 _exit(-1);
343 } else {
344 enc[i].thread_id = i + 1;
345 }
346 }
347 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
348 }
349 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500350 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000351 }
352 for (i = start_thread_id; i <= core_count; i++) {
353 if (enc[i].thread_id == i) {
354 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500355 LOGINFO("Error joining thread %i\n", i);
356 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500357 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000358 _exit(-1);
359 } else {
360 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200361 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000362 if (ret != 0) {
363 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500364 LOGINFO("Thread %i returned an error %i.\n", i, ret);
365 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500366 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000367 _exit(-1);
368 }
369 }
370 } else {
371 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
372 }
373 }
374 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500375 LOGINFO("Error returned by one or more threads.\n");
376 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500377 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000378 _exit(-1);
379 }
380 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500381 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000382 _exit(0);
383 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500384 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000385 std::vector<TarListStruct> FileList;
386 unsigned thread_id = 0;
387 unsigned long long target_size = 0;
388 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500389 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000390
391 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500392 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
393 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500394 LOGINFO("Error in Generate_TarList!\n");
395 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500396 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000397 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000398 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500399 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000400 // Create a backup
401 reg.setfn(tarfn);
402 reg.ItemList = &FileList;
403 reg.thread_id = 0;
404 reg.use_encryption = 0;
405 reg.use_compression = use_compression;
406 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500407 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500408 reg.part_settings = part_settings;
409 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500410 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000411 reg.split_archives = 1;
412 } else {
413 reg.split_archives = 0;
414 }
415 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500416 write(progress_pipe_fd, &file_count, sizeof(file_count));
417 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000418 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500419 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500420 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000421 _exit(-1);
422 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500423 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000424 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000425 }
426 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500427 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600428 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500429 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500430
431 // Parent closes output side
432 close(progress_pipe[1]);
433
434 // Read progress data from children
435 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
436 if (first_data == 0) {
437 // First incoming data is the file count
438 file_count = fs;
439 if (file_count == 0) file_count = 1; // prevent division by 0 below
440 first_data = 1;
441 } else if (first_data == 1) {
442 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500443 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500444 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500445 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600446 if (fs > 0) {
447 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500448 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600449 } else { // fs == 0 increments the file counter
450 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500451 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600452 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500453 }
454 }
455 close(progress_pipe[0]);
456#ifndef BUILD_TWRPTAR_MAIN
457 DataManager::SetValue("tw_file_progress", "");
458 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500459 part_settings->progress->DisplayFileCount(false);
460 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500461
bigbiffce8f83c2015-12-12 18:30:21 -0500462 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400463 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500464 backup_info.SetValue("backup_size", size_backup);
465 if (use_compression && use_encryption)
466 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
467 else if (use_encryption)
468 backup_info.SetValue("backup_type", ENCRYPTED);
469 else if (use_compression)
470 backup_info.SetValue("backup_type", COMPRESSED);
471 else
472 backup_info.SetValue("backup_type", UNCOMPRESSED);
473 backup_info.SetValue("file_count", files_backup);
474 backup_info.SaveValues();
475 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500476#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500477 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500478 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500479 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500480 return 0;
481}
482
bigbiffce8f83c2015-12-12 18:30:21 -0500483int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000484 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600485 pid_t tar_fork_pid;
486 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500487
488 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500489 LOGINFO("Error creating progress tracking pipe\n");
490 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500491 return -1;
492 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000493
bigbiff7abc5fe2015-01-17 16:53:12 -0500494 tar_fork_pid = fork();
495 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000496 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500497 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000498 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500499 close(progress_pipe[0]);
500 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500501 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000502 LOGINFO("Single archive\n");
503 if (extract() != 0)
504 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500505 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000506 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500507 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000508 } else {
509 LOGINFO("Multiple archives\n");
510 string temp;
511 char actual_filename[255];
512 twrpTar tars[9];
513 pthread_t tar_thread[9];
514 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500515 unsigned thread_count = 0, i, start_thread_id = 1;
516 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000517 void *thread_return;
518
519 basefn = tarfn;
520 temp = basefn + "%i%02i";
521 tarfn += "000";
522 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500523 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
524 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500525 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000526 _exit(-1);
527 }
528 if (TWFunc::Get_File_Type(tarfn) != 2) {
529 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
530 tars[0].basefn = basefn;
531 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500532 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500533 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000534 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500535 LOGINFO("Error extracting split archive.\n");
536 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500537 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000538 _exit(-1);
539 }
540 } else {
541 start_thread_id = 0;
542 }
543 // Start threading encrypted restores
544 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500545 LOGINFO("Unable to pthread_attr_init\n");
546 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500547 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000548 _exit(-1);
549 }
550 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500551 LOGINFO("Error setting pthread_attr_setdetachstate\n");
552 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500553 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000554 _exit(-1);
555 }
556 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500557 LOGINFO("Error setting pthread_attr_setscope\n");
558 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500559 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000560 _exit(-1);
561 }
562 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
563 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500564 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000565 _exit(-1);
566 }*/
567 for (i = start_thread_id; i < 9; i++) {
568 sprintf(actual_filename, temp.c_str(), i, 0);
569 if (TWFunc::Path_Exists(actual_filename)) {
570 thread_count++;
571 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500572 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000573 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500574 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500575 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000576 LOGINFO("Creating extract thread ID %i\n", i);
577 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
578 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500579 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 +0000580 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500581 LOGINFO("Error extracting backup in thread %i.\n", i);
582 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500583 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000584 _exit(-1);
585 } else {
586 tars[i].thread_id = i + 1;
587 }
588 }
589 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
590 } else {
591 break;
592 }
593 }
594 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
595 if (tars[i].thread_id == i) {
596 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500597 LOGINFO("Error joining thread %i\n", i);
598 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500599 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000600 _exit(-1);
601 } else {
602 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200603 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000604 if (ret != 0) {
605 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500606 LOGINFO("Thread %i returned an error %i.\n", i, ret);
607 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500608 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000609 _exit(-1);
610 }
611 }
612 } else {
613 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
614 }
615 }
616 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500617 LOGINFO("Error returned by one or more threads.\n");
618 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500619 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000620 _exit(-1);
621 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500622 LOGINFO("Finished encrypted restore.\n");
623 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000624 _exit(0);
625 }
626 }
627 else // parent process
628 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600629 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500630
631 // Parent closes output side
632 close(progress_pipe[1]);
633
634 // Read progress data from children
635 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
636 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500637 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500638 }
639 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500640 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500641
bigbiff7abc5fe2015-01-17 16:53:12 -0500642 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000643 return -1;
644 }
645 }
646 else // fork has failed
647 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500648 close(progress_pipe[0]);
649 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000650 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500651 return -1;
652 }
653 return 0;
654}
655
Dees_Troy83bd4832013-05-04 12:39:56 +0000656int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
657 DIR* d;
658 struct dirent* de;
659 struct stat st;
660 string FileName;
661 struct TarListStruct TarItem;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500662 int ret, file_count;
663 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000664
Dees_Troy83bd4832013-05-04 12:39:56 +0000665 d = opendir(Path.c_str());
666 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500667 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000668 closedir(d);
669 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500670 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000671 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500672 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500673
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600674 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000675 continue;
676 TarItem.fn = FileName;
677 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500678 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000679 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500680 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
681 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500682 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500683 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000684 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
685 stat(FileName.c_str(), &st);
686 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500687 if (de->d_type == DT_REG) {
688 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000689 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500690 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
692 *thread_id = *thread_id + 1;
693 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500694 }
695 }
696 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000697 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500698 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500699}
700
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500701int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000702 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000703 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500704 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500705 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500706 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
707 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500708 return -1;
709 }
710 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500711 LOGINFO("Unable to close tar file\n");
712 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500713 return -1;
714 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600715#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500716 if (part_settings->adbbackup) {
717 if (!twadbbu::Write_TWEOF())
718 return -1;
719 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600720#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500721 return 0;
722}
723
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500724int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500725 if (!part_settings->adbbackup) {
726 LOGINFO("Setting archive type\n");
727 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
728 }
729 else {
730 if (part_settings->adb_compression == 1)
731 current_archive_type = COMPRESSED;
732 else
733 current_archive_type = UNCOMPRESSED;
734 }
n0d33b511632013-03-06 21:14:15 +0200735
bigbiffce8f83c2015-12-12 18:30:21 -0500736 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500737 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000738 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000739 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500740 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500741 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600742 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000743 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500744 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000745 return -1;
746 }
747 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500748 LOGINFO("Decrypted file is not in tar format.\n");
749 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000750 return -1;
751 }
752 if (ret == 3) {
753 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500754 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000755 } else
756 LOGINFO("Extracting encrypted tar.\n");
757 return extractTar();
758 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000759 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500760 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500761 }
762}
763
Dees Troye0a433a2013-12-02 04:10:37 +0000764int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000765 struct stat st;
766 char buf[PATH_MAX];
767 int list_size = TarList->size(), i = 0, archive_count = 0;
768 string temp;
769 char actual_filename[PATH_MAX];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500770 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000771
Dees Troye0a433a2013-12-02 04:10:37 +0000772 if (split_archives) {
773 basefn = tarfn;
774 temp = basefn + "%i%02i";
775 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
776 tarfn = actual_filename;
777 include_root_dir = true;
778 } else {
779 include_root_dir = false;
780 }
bigbiffce8f83c2015-12-12 18:30:21 -0500781
782 if (part_settings->adbbackup)
783 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
784 else
785 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
786
Dees_Troy83bd4832013-05-04 12:39:56 +0000787 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500788 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
789 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000790 return -2;
791 }
792 Archive_Current_Size = 0;
793
794 while (i < list_size) {
795 if (TarList->at(i).thread_id == thread_id) {
796 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400797 lstat(buf, &st);
798 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500799 fs = (unsigned long long)(st.st_size);
800 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000801 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500802 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
803 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000804 return -3;
805 }
806 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500807 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000808 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500809 LOGINFO("Too many archives for thread %i\n", thread_id);
810 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000811 return -4;
812 }
813 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
814 tarfn = actual_filename;
815 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500816 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
817 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000818 return -2;
819 }
820 Archive_Current_Size = 0;
821 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500822 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600823 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500824 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000825 }
Dees Troye0a433a2013-12-02 04:10:37 +0000826 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
827 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500828 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
829 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 return -1;
831 }
832 }
833 i++;
834 }
835 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500836 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
837 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000838 return -3;
839 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600840 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000841 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500842}
843
Dees_Troy83bd4832013-05-04 12:39:56 +0000844void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000845 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600846 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000847 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
848 return (void*)-2;
849 }
850 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
851 return (void*)0;
852}
853
854void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000855 twrpTar* threadTar = (twrpTar*) cookie;
856 int archive_count = 0;
857 string temp = threadTar->basefn + "%i%02i";
858 char actual_filename[255];
859 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
860 while (TWFunc::Path_Exists(actual_filename)) {
861 threadTar->tarfn = actual_filename;
862 if (threadTar->extract() != 0) {
863 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
864 return (void*)-2;
865 }
866 archive_count++;
867 if (archive_count > 99)
868 break;
869 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
870 }
871 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
872 return (void*)0;
873}
874
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500875int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
876 char* charTarFile = (char*) fn.c_str();
877
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100878 if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | 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 -0500879 return -1;
880 removeEOT(charTarFile);
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100881 if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | 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 -0500882 return -1;
883 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500884 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500885 if (tar_append_file(t, file, file) == -1)
886 return -1;
887 }
888 if (tar_append_eof(t) == -1)
889 return -1;
890 if (tar_close(t) == -1)
891 return -1;
892 return 0;
893}
894
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500895int twrpTar::createTar() {
896 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000897 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500898
Dees_Troy83bd4832013-05-04 12:39:56 +0000899 if (use_encryption && use_compression) {
900 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500901 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000902 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000903 int i, pipes[4];
904
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100905 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500906 LOGINFO("Error creating first pipe\n");
907 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500908 return -1;
909 }
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100910 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500911 LOGINFO("Error creating second pipe\n");
912 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500913 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000914 }
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100915 output_fd = open(tarfn.c_str(), O_CLOEXEC | 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 +0000916 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500917 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000918 for (i = 0; i < 4; i++)
919 close(pipes[i]); // close all
920 return -1;
921 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000922 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400923
Dees_Troy83bd4832013-05-04 12:39:56 +0000924 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500925 LOGINFO("pigz fork() failed\n");
926 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000927 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000928 for (i = 0; i < 4; i++)
929 close(pipes[i]); // close all
930 return -1;
931 } else if (pigz_pid == 0) {
932 // pigz Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100933 dup2(pipes[0], STDIN_FILENO);
934 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +0000935 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500936 LOGINFO("execlp pigz ERROR!\n");
937 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000938 _exit(-1);
939 }
940 } else {
941 // Parent
942 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400943
Dees_Troy83bd4832013-05-04 12:39:56 +0000944 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500945 LOGINFO("openaes fork() failed\n");
946 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000947 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000948 for (i = 0; i < 4; i++)
949 close(pipes[i]); // close all
950 return -1;
951 } else if (oaes_pid == 0) {
952 // openaes Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100953 dup2(pipes[2], STDIN_FILENO);
954 dup2(output_fd, STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -0600955 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500956 LOGINFO("execlp openaes ERROR!\n");
957 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000958 _exit(-1);
959 }
960 } else {
961 // Parent
962 close(pipes[0]);
963 close(pipes[2]);
964 close(pipes[3]);
965 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600966 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500967 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100968 if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | 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 +0000969 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500970 LOGINFO("tar_fdopen failed\n");
971 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000972 return -1;
973 }
974 return 0;
975 }
976 }
977 } else if (use_compression) {
978 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500979 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000980 LOGINFO("Using compression...\n");
981 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500982 if (part_settings->adbbackup) {
983 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
984 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
985 }
986 else {
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100987 output_fd = open(tarfn.c_str(), O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
bigbiffce8f83c2015-12-12 18:30:21 -0500988 }
Dees Troy9d723272014-04-07 17:13:10 +0000989 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500990 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000991 return -1;
992 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000993
Fabrice Bellet7884eac2019-12-15 17:49:18 +0100994 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500995 LOGINFO("Error creating pipe\n");
996 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000997 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000998 return -1;
999 }
1000 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001001
Dees_Troy83bd4832013-05-04 12:39:56 +00001002 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001003 LOGINFO("fork() failed\n");
1004 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001005 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001006 close(pigzfd[0]);
1007 close(pigzfd[1]);
1008 return -1;
1009 } else if (pigz_pid == 0) {
1010 // Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001011 dup2(pigzfd[0], STDIN_FILENO); // remap stdin
1012 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001013 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001014 LOGINFO("execlp pigz ERROR!\n");
1015 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001016 _exit(-1);
1017 }
1018 } else {
1019 // Parent
1020 close(pigzfd[0]); // close parent input
1021 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001022 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001023 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001024 if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | 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 +00001025 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001026 LOGINFO("tar_fdopen failed\n");
1027 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001028 return -1;
1029 }
1030 }
1031 } else if (use_encryption) {
1032 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001033 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001034 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001035 int oaesfd[2];
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001036 output_fd = open(tarfn.c_str(), O_CLOEXEC | 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 +00001037 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001038 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001039 return -1;
1040 }
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001041 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001042 LOGINFO("Error creating pipe\n");
1043 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001044 close(output_fd);
1045 return -1;
1046 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001047 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001048
Dees_Troy83bd4832013-05-04 12:39:56 +00001049 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001050 LOGINFO("fork() failed\n");
1051 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001052 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001053 close(oaesfd[0]);
1054 close(oaesfd[1]);
1055 return -1;
1056 } else if (oaes_pid == 0) {
1057 // Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001058 dup2(oaesfd[0], STDIN_FILENO); // remap stdin
1059 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001060 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001061 LOGINFO("execlp openaes ERROR!\n");
1062 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001063 _exit(-1);
1064 }
1065 } else {
1066 // Parent
1067 close(oaesfd[0]); // close parent input
1068 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001069 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001070 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001071 if (tar_fdopen(&t, fd, charRootDir, &tar_type, O_CLOEXEC | 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 +00001072 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001073 LOGINFO("tar_fdopen failed\n");
1074 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001075 return -1;
1076 }
1077 return 0;
1078 }
1079 } else {
1080 // Not compressed or encrypted
nkk71d59d02e2017-06-29 15:16:23 +03001081 current_archive_type = UNCOMPRESSED;
Ethan Yonker472f5062016-02-25 13:47:30 -06001082 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001083 if (part_settings->adbbackup) {
1084 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001085 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001086 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001087 if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_CLOEXEC | 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 -05001088 close(output_fd);
1089 LOGERR("tar_fdopen failed\n");
1090 return -1;
1091 }
1092 }
1093 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001094 tar_type.writefunc = write_tar;
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001095 if (tar_open(&t, charTarFile, &tar_type, O_CLOEXEC | 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 -05001096 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1097 gui_err("backup_error=Error creating backup.");
1098 return -1;
1099 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001100 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001101 }
1102 return 0;
1103}
1104
Dees_Troy83bd4832013-05-04 12:39:56 +00001105int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001106 char* charRootDir = (char*) tardir.c_str();
1107 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001108 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001109
bigbiffce8f83c2015-12-12 18:30:21 -05001110 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001111 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001112 int i, pipes[4];
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001113 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001114 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001115 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001116 return -1;
1117 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001118
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001119 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001120 LOGINFO("Error creating first pipe\n");
1121 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001122 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001123 return -1;
1124 }
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001125 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001126 LOGINFO("Error creating second pipe\n");
1127 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001128 close(pipes[0]);
1129 close(pipes[1]);
1130 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001131 return -1;
1132 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001133 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001134
Dees_Troy83bd4832013-05-04 12:39:56 +00001135 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001136 LOGINFO("pigz fork() failed\n");
1137 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001138 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001139 for (i = 0; i < 4; i++)
1140 close(pipes[i]); // close all
1141 return -1;
1142 } else if (oaes_pid == 0) {
1143 // openaes Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001144 dup2(input_fd, STDIN_FILENO);
1145 dup2(pipes[1], STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -06001146 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001147 LOGINFO("execlp openaes ERROR!\n");
1148 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001149 _exit(-1);
1150 }
1151 } else {
1152 // Parent
1153 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001154
Dees_Troy83bd4832013-05-04 12:39:56 +00001155 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001156 LOGINFO("openaes fork() failed\n");
1157 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001158 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001159 for (i = 0; i < 4; i++)
1160 close(pipes[i]); // close all
1161 return -1;
1162 } else if (pigz_pid == 0) {
1163 // pigz Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001164 dup2(pipes[0], STDIN_FILENO);
1165 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +00001166 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001167 LOGINFO("execlp pigz ERROR!\n");
1168 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001169 _exit(-1);
1170 }
1171 } else {
1172 // Parent
1173 close(pipes[0]); // Close pipes not used by parent
1174 close(pipes[1]);
1175 close(pipes[3]);
1176 fd = pipes[2];
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001177 if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | 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 +00001178 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001179 LOGINFO("tar_fdopen failed\n");
1180 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001181 return -1;
1182 }
1183 }
1184 }
bigbiffce8f83c2015-12-12 18:30:21 -05001185 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001186 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001187 int oaesfd[2];
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001188 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001189 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001190 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001191 return -1;
1192 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001193
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001194 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001195 LOGINFO("Error creating pipe\n");
1196 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001197 close(input_fd);
1198 return -1;
1199 }
1200
Dees_Troy83bd4832013-05-04 12:39:56 +00001201 oaes_pid = fork();
1202 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001203 LOGINFO("fork() failed\n");
1204 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001205 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001206 close(oaesfd[0]);
1207 close(oaesfd[1]);
1208 return -1;
1209 } else if (oaes_pid == 0) {
1210 // Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001211 dup2(oaesfd[1], STDOUT_FILENO); // remap stdout
1212 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001213 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001214 LOGINFO("execlp openaes ERROR!\n");
1215 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001216 _exit(-1);
1217 }
1218 } else {
1219 // Parent
1220 close(oaesfd[1]); // close parent output
1221 fd = oaesfd[0]; // copy parent input
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001222 if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | 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 +00001223 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001224 LOGINFO("tar_fdopen failed\n");
1225 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001226 return -1;
1227 }
1228 }
bigbiffce8f83c2015-12-12 18:30:21 -05001229 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001230 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001231
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -04001232 LOGINFO("Opening gzip compressed tar...\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001233 if (part_settings->adbbackup) {
1234 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001235 input_fd = open(TW_ADB_RESTORE, O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001236 }
1237 else
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001238 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001239
Dees Troy9d723272014-04-07 17:13:10 +00001240 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001241 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001242 return -1;
1243 }
bigbiffce8f83c2015-12-12 18:30:21 -05001244
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001245 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001246 LOGINFO("Error creating pipe\n");
1247 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001248 close(input_fd);
1249 return -1;
1250 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001251
1252 pigz_pid = fork();
1253 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001254 LOGINFO("fork() failed\n");
1255 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001256 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001257 close(pigzfd[0]);
1258 close(pigzfd[1]);
1259 return -1;
1260 } else if (pigz_pid == 0) {
1261 // Child
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001262 dup2(pigzfd[1], STDOUT_FILENO); // remap stdout
1263 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001264 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001265 LOGINFO("execlp pigz ERROR!\n");
Ethan Yonker74db1572015-10-28 12:44:49 -05001266 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001267 _exit(-1);
1268 }
1269 } else {
1270 // Parent
1271 close(pigzfd[1]); // close parent output
1272 fd = pigzfd[0]; // copy parent input
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001273 if (tar_fdopen(&t, fd, charRootDir, NULL, O_CLOEXEC | 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 +00001274 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001275 LOGINFO("tar_fdopen failed\n");
1276 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001277 return -1;
1278 }
1279 }
bigbiffce8f83c2015-12-12 18:30:21 -05001280 } else {
1281 if (part_settings->adbbackup) {
1282 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1283 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001284 if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_CLOEXEC | 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 -05001285 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1286 gui_err("restore_error=Error during restore process.");
1287 return -1;
1288 }
1289 }
1290 else {
Fabrice Bellet7884eac2019-12-15 17:49:18 +01001291 if (tar_open(&t, charTarFile, NULL, O_CLOEXEC | 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 -05001292 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1293 gui_err("restore_error=Error during restore process.");
1294 return -1;
1295 }
1296 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001297 }
1298 return 0;
1299}
1300
1301string twrpTar::Strip_Root_Dir(string Path) {
1302 string temp;
1303 size_t slash;
1304
1305 if (Path.substr(0, 1) == "/")
1306 temp = Path.substr(1, Path.size() - 1);
1307 else
1308 temp = Path;
1309 slash = temp.find("/");
1310 if (slash == string::npos)
1311 return temp;
1312 else {
1313 string stripped;
1314
1315 stripped = temp.substr(slash, temp.size() - slash);
1316 return stripped;
1317 }
1318 return temp;
1319}
1320
1321int twrpTar::addFile(string fn, bool include_root) {
1322 char* charTarFile = (char*) fn.c_str();
1323 if (include_root) {
1324 if (tar_append_file(t, charTarFile, NULL) == -1)
1325 return -1;
1326 } else {
1327 string temp = Strip_Root_Dir(fn);
1328 char* charTarPath = (char*) temp.c_str();
1329 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1330 return -1;
1331 }
1332 return 0;
1333}
1334
Dees_Troy83bd4832013-05-04 12:39:56 +00001335int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001336 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001337 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001338 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001339 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001340 tar_close(t);
1341 return -1;
1342 }
1343 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001344 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001345 return -1;
1346 }
bigbiffce8f83c2015-12-12 18:30:21 -05001347 if (current_archive_type > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001348 int status;
1349 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1350 return -1;
1351 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1352 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001353 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001354 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001355 if (!part_settings->adbbackup) {
1356 if (use_compression && !use_encryption) {
1357 string gzname = tarfn + ".gz";
1358 if (TWFunc::Path_Exists(gzname)) {
1359 rename(gzname.c_str(), tarfn.c_str());
1360 }
Dees Troye0a433a2013-12-02 04:10:37 +00001361 }
bigbiffce8f83c2015-12-12 18:30:21 -05001362 if (TWFunc::Get_File_Size(tarfn) == 0) {
1363 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1364 return -1;
1365 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001366#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001367 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001368#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001369 }
1370 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001371#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001372 if (!twadbbu::Write_TWEOF())
1373 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001374#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001375 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001376 if (input_fd >= 0)
1377 close(input_fd);
1378 if (output_fd >= 0)
1379 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001380 return 0;
1381}
1382
1383int twrpTar::removeEOT(string tarFile) {
1384 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001385 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001386 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001387 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001388 tar_skip_regfile(t);
1389 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001390 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001391 if (tar_close(t) == -1)
1392 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001393 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001394 return -1;
1395 return 0;
1396}
1397
n0d33b511632013-03-06 21:14:15 +02001398int twrpTar::entryExists(string entry) {
1399 char* searchstr = (char*)entry.c_str();
1400 int ret;
1401
bigbiffce8f83c2015-12-12 18:30:21 -05001402 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001403
Dees_Troy83bd4832013-05-04 12:39:56 +00001404 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001405 ret = 0;
1406 else
1407 ret = tar_find(t, searchstr);
1408
Dees_Troy83bd4832013-05-04 12:39:56 +00001409 if (closeTar() != 0)
1410 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001411
1412 return ret;
1413}
1414
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001415unsigned long long twrpTar::get_size() {
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04001416 if (part_settings->adbbackup || TWFunc::Path_Exists(tarfn)) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001417 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001418 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001419 } else {
1420 LOGINFO("Multiple archives\n");
1421 string temp;
1422 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001423 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001424 unsigned long long total_restore_size = 0;
1425
1426 basefn = tarfn;
1427 temp = basefn + "%i%02i";
1428 tarfn += "000";
1429 thread_id = 0;
1430 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001431 if (!part_settings->adbbackup) {
1432 if (!TWFunc::Path_Exists(actual_filename)) {
1433 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1434 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001435 }
bigbiffce8f83c2015-12-12 18:30:21 -05001436 for (int i = 0; i < 9; i++) {
1437 archive_count = 0;
1438 sprintf(actual_filename, temp.c_str(), i, archive_count);
1439 while (TWFunc::Path_Exists(actual_filename)) {
1440 total_restore_size += uncompressedSize(actual_filename);
1441 archive_count++;
1442 if (archive_count > 99)
1443 break;
1444 sprintf(actual_filename, temp.c_str(), i, archive_count);
1445 }
1446 }
1447 #ifndef BUILD_TWRPTAR_MAIN
1448 if (!part_settings->adbbackup) {
1449 InfoManager backup_info(tarfn + ".info");
1450 backup_info.SetValue("backup_size", total_restore_size);
1451 backup_info.SetValue("backup_type", current_archive_type);
1452 backup_info.SaveValues();
1453 }
1454 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001455 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001456 return total_restore_size;
1457 }
1458 return 0;
1459}
1460
bigbiffce8f83c2015-12-12 18:30:21 -05001461unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001462 unsigned long long total_size = 0;
1463 string Tar, Command, result;
1464 vector<string> split;
1465
bigbiffce8f83c2015-12-12 18:30:21 -05001466 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1467 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001468 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001469 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001470 // Compressed
1471 Command = "pigz -l '" + filename + "'";
1472 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1473 we get the uncompressed size at once. */
bigbiff56b02eb2020-07-06 20:24:34 -04001474 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001475 if (!result.empty()) {
1476 /* Expected output:
1477 compressed original reduced name
1478 95855838 179403776 -1.3% data.yaffs2.win
1479 ^
1480 split[5]
1481 */
1482 split = TWFunc::split_string(result, ' ', true);
1483 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001484 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001485 }
bigbiffce8f83c2015-12-12 18:30:21 -05001486 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001487 // File is encrypted and may be compressed
1488 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001489 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001490 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001491 total_size = TWFunc::Get_File_Size(filename);
1492 } else if (ret == 1) {
1493 LOGERR("Decrypted file is not in tar format.\n");
1494 total_size = TWFunc::Get_File_Size(filename);
1495 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001496 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1497 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1498 we get the uncompressed size at once. */
bigbiff56b02eb2020-07-06 20:24:34 -04001499 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001500 if (!result.empty()) {
1501 LOGINFO("result was: '%s'\n", result.c_str());
1502 /* Expected output:
1503 compressed original reduced name
1504 95855838 179403776 -1.3% data.yaffs2.win
1505 ^
1506 split[5]
1507 */
1508 split = TWFunc::split_string(result, ' ', true);
1509 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001510 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001511 }
1512 } else {
1513 total_size = TWFunc::Get_File_Size(filename);
1514 }
1515 }
1516
1517 return total_size;
1518}
1519
Dees_Troye34c1332013-02-06 19:13:00 +00001520extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1521 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001522}
Ethan Yonker472f5062016-02-25 13:47:30 -06001523
1524extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1525 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1526}