blob: 6c9e758d7dff4ca959307a5e57ef4cca961ee440 [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
bigbiff7ba75002020-04-11 20:47:09 -04003 Copyright 2013 to 2020 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"
bigbiff7ba75002020-04-11 20:47:09 -040050
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050051#ifndef BUILD_TWRPTAR_MAIN
52#include "data.hpp"
53#include "infomanager.hpp"
Ethan Yonkerf1179622016-08-25 15:32:21 -050054#include "set_metadata.h"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050055#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050056
Ethan Yonker79f88bd2016-12-09 14:52:12 -060057#ifdef TW_INCLUDE_FBE
bigbiff7ba75002020-04-11 20:47:09 -040058#ifdef USE_FSCRYPT
59#include "fscrypt_policy.h"
60#else
Ethan Yonker79f88bd2016-12-09 14:52:12 -060061#include "crypto/ext4crypt/ext4crypt_tar.h"
bigbiff7ba75002020-04-11 20:47:09 -040062#endif
63#endif
64
65#ifdef TW_INCLUDE_FBE
66#ifdef USE_FSCRYPT
67#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR | TAR_STORE_FSCRYPT_POL
68#else
69#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR | TAR_STORE_EXT4_POL
70#endif
Ethan Yonker79f88bd2016-12-09 14:52:12 -060071#else
Ethan Yonker8d039f72017-02-03 14:26:15 -060072#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR
Ethan Yonker79f88bd2016-12-09 14:52:12 -060073#endif
74
bigbiff bigbiff9c754052013-01-09 09:09:08 -050075using namespace std;
76
Dees_Troy83bd4832013-05-04 12:39:56 +000077twrpTar::twrpTar(void) {
78 use_encryption = 0;
79 userdata_encryption = 0;
80 use_compression = 0;
81 split_archives = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +000082 pigz_pid = 0;
83 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000084 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060085 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000086 include_root_dir = true;
Ethan Yonkerf1179622016-08-25 15:32:21 -050087 tar_type.openfunc = open;
88 tar_type.closefunc = close;
89 tar_type.readfunc = read;
Ethan Yonkerea2fcf02016-09-12 16:07:19 -050090 input_fd = -1;
91 output_fd = -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -060092 backup_exclusions = NULL;
Ethan Yonker79f88bd2016-12-09 14:52:12 -060093#ifdef TW_INCLUDE_FBE
bigbiff7ba75002020-04-11 20:47:09 -040094#ifdef USE_FSCRYPT
95 fscrypt_set_mode();
96#else
Ethan Yonker79f88bd2016-12-09 14:52:12 -060097 e4crypt_set_mode();
98#endif
bigbiff7ba75002020-04-11 20:47:09 -040099#endif
Dees_Troy83bd4832013-05-04 12:39:56 +0000100}
101
102twrpTar::~twrpTar(void) {
103 // Do nothing
104}
105
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500106void twrpTar::setfn(string fn) {
107 tarfn = fn;
108}
109
110void twrpTar::setdir(string dir) {
111 tardir = dir;
112}
113
Dees Troye0a433a2013-12-02 04:10:37 +0000114void twrpTar::setsize(unsigned long long backup_size) {
115 Total_Backup_Size = backup_size;
116}
117
Ethan Yonker87af5632014-02-10 11:56:35 -0600118void twrpTar::setpassword(string pass) {
119 password = pass;
120}
121
bigbiff7abc5fe2015-01-17 16:53:12 -0500122void twrpTar::Signal_Kill(int signum) {
123 _exit(255);
124}
125
bigbiffce8f83c2015-12-12 18:30:21 -0500126void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
127 current_archive_type = archive_type;
128}
129
130int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000131 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600132 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500133
134 file_count = 0;
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600135 if (backup_exclusions == NULL) {
136 LOGINFO("backup_exclusions is NULL\n");
137 return -1;
138 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500139
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600140#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500141 if (part_settings->adbbackup) {
142 std::string Backup_FileName(tarfn);
143 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
144 return -1;
145 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600146#endif
bigbiffce8f83c2015-12-12 18:30:21 -0500147
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500148 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500149 LOGINFO("Error creating progress tracking pipe\n");
150 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500151 return -1;
152 }
bigbiffce8f83c2015-12-12 18:30:21 -0500153 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000154 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500155 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500156 close(progress_pipe[0]);
157 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500158 return -1;
159 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500160
bigbiffce8f83c2015-12-12 18:30:21 -0500161 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500162 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500163 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500164 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500165 close(progress_pipe[0]);
166 progress_pipe_fd = progress_pipe[1];
167
Dees_Troy83bd4832013-05-04 12:39:56 +0000168 if (use_encryption || userdata_encryption) {
169 LOGINFO("Using encryption\n");
170 DIR* d;
171 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200172 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
173 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000174 int item_len, ret, thread_error = 0;
175 std::vector<TarListStruct> RegularList;
176 std::vector<TarListStruct> EncryptList;
177 string FileName;
178 struct TarListStruct TarItem;
179 twrpTar reg, enc[9];
180 struct stat st;
181 pthread_t enc_thread[9];
182 pthread_attr_t tattr;
183 void *thread_return;
184
185 core_count = sysconf(_SC_NPROCESSORS_CONF);
186 if (core_count > 8)
187 core_count = 8;
that2252d242015-04-03 22:33:04 +0200188 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000189 Archive_Current_Size = 0;
190
191 d = opendir(tardir.c_str());
192 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500193 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500194 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000195 _exit(-1);
196 }
197 // Figure out the size of all data to be encrypted and create a list of unencrypted files
198 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500199 FileName = tardir + "/" + de->d_name;
200
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600201 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000202 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500203 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000204 item_len = strlen(de->d_name);
205 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 -0500206 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
207 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500208 LOGINFO("Error in Generate_TarList with regular list!\n");
209 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000210 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500211 close(progress_pipe_fd);
212 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000213 _exit(-1);
214 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500215 file_count = (unsigned long long)(ret);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600216 regular_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000217 } else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600218 encrypt_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000219 }
220 } else if (de->d_type == DT_REG) {
221 stat(FileName.c_str(), &st);
222 encrypt_size += (unsigned long long)(st.st_size);
223 }
224 }
225 closedir(d);
226
227 target_size = encrypt_size / core_count;
228 target_size++;
229 LOGINFO(" Unencrypted size: %llu\n", regular_size);
230 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
231 LOGINFO(" Target size : %llu\n", target_size);
232 if (!userdata_encryption) {
233 enc_thread_id = 0;
234 start_thread_id = 0;
235 core_count--;
236 }
237 Archive_Current_Size = 0;
238
239 d = opendir(tardir.c_str());
240 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500241 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 _exit(-1);
244 }
245 // Divide up the encrypted file list for threading
246 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500247 FileName = tardir + "/" + de->d_name;
248
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600249 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000250 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500251 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000252 item_len = strlen(de->d_name);
253 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
254 // Do nothing, we added these to RegularList earlier
255 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500256 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500257 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
258 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500259 LOGINFO("Error in Generate_TarList with encrypted list!\n");
260 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000261 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500262 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000263 _exit(-1);
264 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500265 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000266 }
267 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
268 stat(FileName.c_str(), &st);
269 if (de->d_type == DT_REG)
270 Archive_Current_Size += (unsigned long long)(st.st_size);
271 TarItem.fn = FileName;
272 TarItem.thread_id = enc_thread_id;
273 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500274 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000275 }
276 }
277 closedir(d);
278 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500279 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 -0500280 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500281 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500282 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000283 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500284 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500285 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500286 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000287 }
288
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500289 // Send file count to parent
290 write(progress_pipe_fd, &file_count, sizeof(file_count));
291 // Send backup size to parent
292 total_size = regular_size + encrypt_size;
293 write(progress_pipe_fd, &total_size, sizeof(total_size));
294
Dees_Troy83bd4832013-05-04 12:39:56 +0000295 if (userdata_encryption) {
296 // Create a backup of unencrypted data
297 reg.setfn(tarfn);
298 reg.ItemList = &RegularList;
299 reg.thread_id = 0;
300 reg.use_encryption = 0;
301 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000302 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500303 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500304 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000305 LOGINFO("Creating unencrypted backup...\n");
306 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500307 LOGINFO("Error creating unencrypted backup.\n");
308 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500309 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000310 _exit(-1);
311 }
312 }
313
314 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500315 LOGINFO("Unable to pthread_attr_init\n");
316 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500317 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000318 _exit(-1);
319 }
320 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500321 LOGINFO("Error setting pthread_attr_setdetachstate\n");
322 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500323 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000324 _exit(-1);
325 }
326 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500327 LOGINFO("Error setting pthread_attr_setscope\n");
328 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500329 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000330 _exit(-1);
331 }
332 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
333 LOGERR("Error setting pthread_attr_setstacksize\n");
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100334 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000335 _exit(-1);
336 }*/
337
338 // Create threads for the divided up encryption lists
339 for (i = start_thread_id; i <= core_count; i++) {
340 enc[i].setdir(tardir);
341 enc[i].setfn(tarfn);
342 enc[i].ItemList = &EncryptList;
343 enc[i].thread_id = i;
344 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500345 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000346 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000347 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500348 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500349 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000350 LOGINFO("Start encryption thread %i\n", i);
351 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
352 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500353 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 +0000354 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500355 LOGINFO("Error creating encrypted backup %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 enc[i].thread_id = i + 1;
361 }
362 }
363 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
364 }
365 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500366 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000367 }
368 for (i = start_thread_id; i <= core_count; i++) {
369 if (enc[i].thread_id == i) {
370 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500371 LOGINFO("Error joining thread %i\n", i);
372 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500373 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000374 _exit(-1);
375 } else {
376 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200377 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000378 if (ret != 0) {
379 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500380 LOGINFO("Thread %i returned an error %i.\n", i, ret);
381 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500382 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000383 _exit(-1);
384 }
385 }
386 } else {
387 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
388 }
389 }
390 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500391 LOGINFO("Error returned by one or more threads.\n");
392 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500393 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000394 _exit(-1);
395 }
396 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500397 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000398 _exit(0);
399 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500400 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000401 std::vector<TarListStruct> FileList;
402 unsigned thread_id = 0;
403 unsigned long long target_size = 0;
404 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500405 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000406
407 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500408 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
409 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500410 LOGINFO("Error in Generate_TarList!\n");
411 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500412 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000413 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000414 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500415 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000416 // Create a backup
417 reg.setfn(tarfn);
418 reg.ItemList = &FileList;
419 reg.thread_id = 0;
420 reg.use_encryption = 0;
421 reg.use_compression = use_compression;
422 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500423 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500424 reg.part_settings = part_settings;
425 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500426 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000427 reg.split_archives = 1;
428 } else {
429 reg.split_archives = 0;
430 }
431 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500432 write(progress_pipe_fd, &file_count, sizeof(file_count));
433 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000434 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500435 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500436 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000437 _exit(-1);
438 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500439 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000440 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000441 }
442 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500443 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600444 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500445 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500446
447 // Parent closes output side
448 close(progress_pipe[1]);
449
450 // Read progress data from children
451 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
452 if (first_data == 0) {
453 // First incoming data is the file count
454 file_count = fs;
455 if (file_count == 0) file_count = 1; // prevent division by 0 below
456 first_data = 1;
457 } else if (first_data == 1) {
458 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500459 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500460 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500461 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600462 if (fs > 0) {
463 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500464 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600465 } else { // fs == 0 increments the file counter
466 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500467 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600468 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500469 }
470 }
471 close(progress_pipe[0]);
472#ifndef BUILD_TWRPTAR_MAIN
473 DataManager::SetValue("tw_file_progress", "");
474 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500475 part_settings->progress->DisplayFileCount(false);
476 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500477
bigbiffce8f83c2015-12-12 18:30:21 -0500478 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400479 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500480 backup_info.SetValue("backup_size", size_backup);
481 if (use_compression && use_encryption)
482 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
483 else if (use_encryption)
484 backup_info.SetValue("backup_type", ENCRYPTED);
485 else if (use_compression)
486 backup_info.SetValue("backup_type", COMPRESSED);
487 else
488 backup_info.SetValue("backup_type", UNCOMPRESSED);
489 backup_info.SetValue("file_count", files_backup);
490 backup_info.SaveValues();
491 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500492#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500493 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500494 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500495 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500496 return 0;
497}
498
bigbiffce8f83c2015-12-12 18:30:21 -0500499int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000500 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600501 pid_t tar_fork_pid;
502 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500503
504 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500505 LOGINFO("Error creating progress tracking pipe\n");
506 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500507 return -1;
508 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000509
bigbiff7abc5fe2015-01-17 16:53:12 -0500510 tar_fork_pid = fork();
511 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000512 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500513 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000514 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500515 close(progress_pipe[0]);
516 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500517 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000518 LOGINFO("Single archive\n");
519 if (extract() != 0)
520 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500521 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000522 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500523 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000524 } else {
525 LOGINFO("Multiple archives\n");
526 string temp;
527 char actual_filename[255];
528 twrpTar tars[9];
529 pthread_t tar_thread[9];
530 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500531 unsigned thread_count = 0, i, start_thread_id = 1;
532 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 void *thread_return;
534
535 basefn = tarfn;
536 temp = basefn + "%i%02i";
537 tarfn += "000";
538 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500539 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
540 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500541 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000542 _exit(-1);
543 }
544 if (TWFunc::Get_File_Type(tarfn) != 2) {
545 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
546 tars[0].basefn = basefn;
547 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500548 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500549 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500551 LOGINFO("Error extracting split archive.\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 } else {
557 start_thread_id = 0;
558 }
559 // Start threading encrypted restores
560 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500561 LOGINFO("Unable to pthread_attr_init\n");
562 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500563 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000564 _exit(-1);
565 }
566 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500567 LOGINFO("Error setting pthread_attr_setdetachstate\n");
568 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500569 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000570 _exit(-1);
571 }
572 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500573 LOGINFO("Error setting pthread_attr_setscope\n");
574 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500575 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000576 _exit(-1);
577 }
578 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
579 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500580 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000581 _exit(-1);
582 }*/
583 for (i = start_thread_id; i < 9; i++) {
584 sprintf(actual_filename, temp.c_str(), i, 0);
585 if (TWFunc::Path_Exists(actual_filename)) {
586 thread_count++;
587 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500588 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000589 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500590 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500591 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000592 LOGINFO("Creating extract thread ID %i\n", i);
593 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
594 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500595 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 +0000596 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500597 LOGINFO("Error extracting backup in 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 tars[i].thread_id = i + 1;
603 }
604 }
605 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
606 } else {
607 break;
608 }
609 }
610 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
611 if (tars[i].thread_id == i) {
612 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500613 LOGINFO("Error joining thread %i\n", i);
614 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500615 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000616 _exit(-1);
617 } else {
618 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200619 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000620 if (ret != 0) {
621 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500622 LOGINFO("Thread %i returned an error %i.\n", i, ret);
623 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500624 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000625 _exit(-1);
626 }
627 }
628 } else {
629 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
630 }
631 }
632 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500633 LOGINFO("Error returned by one or more threads.\n");
634 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500635 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000636 _exit(-1);
637 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500638 LOGINFO("Finished encrypted restore.\n");
639 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000640 _exit(0);
641 }
642 }
643 else // parent process
644 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600645 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500646
647 // Parent closes output side
648 close(progress_pipe[1]);
649
650 // Read progress data from children
651 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
652 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500653 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500654 }
655 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500656 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500657
bigbiff7abc5fe2015-01-17 16:53:12 -0500658 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000659 return -1;
660 }
661 }
662 else // fork has failed
663 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500664 close(progress_pipe[0]);
665 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000666 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500667 return -1;
668 }
669 return 0;
670}
671
Dees_Troy83bd4832013-05-04 12:39:56 +0000672int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
673 DIR* d;
674 struct dirent* de;
675 struct stat st;
676 string FileName;
677 struct TarListStruct TarItem;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500678 int ret, file_count;
679 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000680
Dees_Troy83bd4832013-05-04 12:39:56 +0000681 d = opendir(Path.c_str());
682 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500683 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000684 closedir(d);
685 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500686 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000687 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500688 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500689
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600690 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 continue;
692 TarItem.fn = FileName;
693 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500694 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000695 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500696 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
697 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500698 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500699 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000700 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
701 stat(FileName.c_str(), &st);
702 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500703 if (de->d_type == DT_REG) {
704 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000705 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500706 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000707 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
708 *thread_id = *thread_id + 1;
709 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500710 }
711 }
712 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000713 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500714 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500715}
716
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500717int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000718 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000719 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500720 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500721 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500722 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
723 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500724 return -1;
725 }
726 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500727 LOGINFO("Unable to close tar file\n");
728 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500729 return -1;
730 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600731#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500732 if (part_settings->adbbackup) {
733 if (!twadbbu::Write_TWEOF())
734 return -1;
735 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600736#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500737 return 0;
738}
739
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500740int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500741 if (!part_settings->adbbackup) {
742 LOGINFO("Setting archive type\n");
743 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
744 }
745 else {
746 if (part_settings->adb_compression == 1)
747 current_archive_type = COMPRESSED;
748 else
749 current_archive_type = UNCOMPRESSED;
750 }
n0d33b511632013-03-06 21:14:15 +0200751
bigbiffce8f83c2015-12-12 18:30:21 -0500752 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500753 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000754 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000755 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500756 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500757 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600758 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000759 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500760 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000761 return -1;
762 }
763 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500764 LOGINFO("Decrypted file is not in tar format.\n");
765 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000766 return -1;
767 }
768 if (ret == 3) {
769 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500770 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000771 } else
772 LOGINFO("Extracting encrypted tar.\n");
773 return extractTar();
774 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000775 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500776 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500777 }
778}
779
Dees Troye0a433a2013-12-02 04:10:37 +0000780int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000781 struct stat st;
782 char buf[PATH_MAX];
783 int list_size = TarList->size(), i = 0, archive_count = 0;
784 string temp;
785 char actual_filename[PATH_MAX];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500786 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000787
Dees Troye0a433a2013-12-02 04:10:37 +0000788 if (split_archives) {
789 basefn = tarfn;
790 temp = basefn + "%i%02i";
791 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
792 tarfn = actual_filename;
793 include_root_dir = true;
794 } else {
795 include_root_dir = false;
796 }
bigbiffce8f83c2015-12-12 18:30:21 -0500797
798 if (part_settings->adbbackup)
799 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
800 else
801 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
802
Dees_Troy83bd4832013-05-04 12:39:56 +0000803 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500804 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
805 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000806 return -2;
807 }
808 Archive_Current_Size = 0;
809
810 while (i < list_size) {
811 if (TarList->at(i).thread_id == thread_id) {
812 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400813 lstat(buf, &st);
814 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500815 fs = (unsigned long long)(st.st_size);
816 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000817 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500818 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
819 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000820 return -3;
821 }
822 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500823 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000824 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500825 LOGINFO("Too many archives for thread %i\n", thread_id);
826 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000827 return -4;
828 }
829 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
830 tarfn = actual_filename;
831 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500832 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
833 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000834 return -2;
835 }
836 Archive_Current_Size = 0;
837 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500838 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600839 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500840 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000841 }
Dees Troye0a433a2013-12-02 04:10:37 +0000842 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
843 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500844 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
845 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000846 return -1;
847 }
848 }
849 i++;
850 }
851 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500852 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
853 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000854 return -3;
855 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600856 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000857 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500858}
859
Dees_Troy83bd4832013-05-04 12:39:56 +0000860void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000861 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600862 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000863 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
864 return (void*)-2;
865 }
866 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
867 return (void*)0;
868}
869
870void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000871 twrpTar* threadTar = (twrpTar*) cookie;
872 int archive_count = 0;
873 string temp = threadTar->basefn + "%i%02i";
874 char actual_filename[255];
875 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
876 while (TWFunc::Path_Exists(actual_filename)) {
877 threadTar->tarfn = actual_filename;
878 if (threadTar->extract() != 0) {
879 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
880 return (void*)-2;
881 }
882 archive_count++;
883 if (archive_count > 99)
884 break;
885 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
886 }
887 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
888 return (void*)0;
889}
890
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500891int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
892 char* charTarFile = (char*) fn.c_str();
893
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100894 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 -0500895 return -1;
896 removeEOT(charTarFile);
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100897 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 -0500898 return -1;
899 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500900 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500901 if (tar_append_file(t, file, file) == -1)
902 return -1;
903 }
904 if (tar_append_eof(t) == -1)
905 return -1;
906 if (tar_close(t) == -1)
907 return -1;
908 return 0;
909}
910
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500911int twrpTar::createTar() {
912 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000913 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500914
Dees_Troy83bd4832013-05-04 12:39:56 +0000915 if (use_encryption && use_compression) {
916 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500917 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000918 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000919 int i, pipes[4];
920
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100921 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500922 LOGINFO("Error creating first pipe\n");
923 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500924 return -1;
925 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100926 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500927 LOGINFO("Error creating second pipe\n");
928 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500929 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000930 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100931 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 +0000932 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500933 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000934 for (i = 0; i < 4; i++)
935 close(pipes[i]); // close all
936 return -1;
937 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000938 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400939
Dees_Troy83bd4832013-05-04 12:39:56 +0000940 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500941 LOGINFO("pigz fork() failed\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 for (i = 0; i < 4; i++)
945 close(pipes[i]); // close all
946 return -1;
947 } else if (pigz_pid == 0) {
948 // pigz Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100949 dup2(pipes[0], STDIN_FILENO);
950 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +0000951 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500952 LOGINFO("execlp pigz ERROR!\n");
953 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000954 _exit(-1);
955 }
956 } else {
957 // Parent
958 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400959
Dees_Troy83bd4832013-05-04 12:39:56 +0000960 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500961 LOGINFO("openaes fork() failed\n");
962 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000963 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000964 for (i = 0; i < 4; i++)
965 close(pipes[i]); // close all
966 return -1;
967 } else if (oaes_pid == 0) {
968 // openaes Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100969 dup2(pipes[2], STDIN_FILENO);
970 dup2(output_fd, STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -0600971 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500972 LOGINFO("execlp openaes ERROR!\n");
973 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000974 _exit(-1);
975 }
976 } else {
977 // Parent
978 close(pipes[0]);
979 close(pipes[2]);
980 close(pipes[3]);
981 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600982 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500983 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100984 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 +0000985 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500986 LOGINFO("tar_fdopen failed\n");
987 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000988 return -1;
989 }
990 return 0;
991 }
992 }
993 } else if (use_compression) {
994 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500995 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000996 LOGINFO("Using compression...\n");
997 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500998 if (part_settings->adbbackup) {
999 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
1000 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1001 }
1002 else {
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001003 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 -05001004 }
Dees Troy9d723272014-04-07 17:13:10 +00001005 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001006 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001007 return -1;
1008 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001009
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001010 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001011 LOGINFO("Error creating pipe\n");
1012 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001013 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001014 return -1;
1015 }
1016 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001017
Dees_Troy83bd4832013-05-04 12:39:56 +00001018 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001019 LOGINFO("fork() failed\n");
1020 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001021 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001022 close(pigzfd[0]);
1023 close(pigzfd[1]);
1024 return -1;
1025 } else if (pigz_pid == 0) {
1026 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001027 dup2(pigzfd[0], STDIN_FILENO); // remap stdin
1028 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001029 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001030 LOGINFO("execlp pigz ERROR!\n");
1031 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001032 _exit(-1);
1033 }
1034 } else {
1035 // Parent
1036 close(pigzfd[0]); // close parent input
1037 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001038 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001039 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001040 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 +00001041 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001042 LOGINFO("tar_fdopen failed\n");
1043 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001044 return -1;
1045 }
1046 }
1047 } else if (use_encryption) {
1048 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001049 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001050 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001051 int oaesfd[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001052 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 +00001053 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001054 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001055 return -1;
1056 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001057 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001058 LOGINFO("Error creating pipe\n");
1059 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001060 close(output_fd);
1061 return -1;
1062 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001063 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001064
Dees_Troy83bd4832013-05-04 12:39:56 +00001065 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001066 LOGINFO("fork() failed\n");
1067 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001068 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001069 close(oaesfd[0]);
1070 close(oaesfd[1]);
1071 return -1;
1072 } else if (oaes_pid == 0) {
1073 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001074 dup2(oaesfd[0], STDIN_FILENO); // remap stdin
1075 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001076 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001077 LOGINFO("execlp openaes ERROR!\n");
1078 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001079 _exit(-1);
1080 }
1081 } else {
1082 // Parent
1083 close(oaesfd[0]); // close parent input
1084 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001085 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001086 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001087 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 +00001088 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001089 LOGINFO("tar_fdopen failed\n");
1090 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001091 return -1;
1092 }
1093 return 0;
1094 }
1095 } else {
1096 // Not compressed or encrypted
nkk71d59d02e2017-06-29 15:16:23 +03001097 current_archive_type = UNCOMPRESSED;
Ethan Yonker472f5062016-02-25 13:47:30 -06001098 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001099 if (part_settings->adbbackup) {
1100 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001101 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001102 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001103 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 -05001104 close(output_fd);
1105 LOGERR("tar_fdopen failed\n");
1106 return -1;
1107 }
1108 }
1109 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001110 tar_type.writefunc = write_tar;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001111 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 -05001112 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1113 gui_err("backup_error=Error creating backup.");
1114 return -1;
1115 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001116 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001117 }
1118 return 0;
1119}
1120
Dees_Troy83bd4832013-05-04 12:39:56 +00001121int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001122 char* charRootDir = (char*) tardir.c_str();
1123 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001124 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001125
bigbiffce8f83c2015-12-12 18:30:21 -05001126 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001127 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001128 int i, pipes[4];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001129 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001130 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001131 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001132 return -1;
1133 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001134
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001135 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001136 LOGINFO("Error creating first pipe\n");
1137 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001138 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001139 return -1;
1140 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001141 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001142 LOGINFO("Error creating second pipe\n");
1143 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001144 close(pipes[0]);
1145 close(pipes[1]);
1146 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001147 return -1;
1148 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001149 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001150
Dees_Troy83bd4832013-05-04 12:39:56 +00001151 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001152 LOGINFO("pigz fork() failed\n");
1153 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001154 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001155 for (i = 0; i < 4; i++)
1156 close(pipes[i]); // close all
1157 return -1;
1158 } else if (oaes_pid == 0) {
1159 // openaes Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001160 dup2(input_fd, STDIN_FILENO);
1161 dup2(pipes[1], STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -06001162 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001163 LOGINFO("execlp openaes ERROR!\n");
1164 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001165 _exit(-1);
1166 }
1167 } else {
1168 // Parent
1169 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001170
Dees_Troy83bd4832013-05-04 12:39:56 +00001171 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001172 LOGINFO("openaes fork() failed\n");
1173 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001174 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001175 for (i = 0; i < 4; i++)
1176 close(pipes[i]); // close all
1177 return -1;
1178 } else if (pigz_pid == 0) {
1179 // pigz Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001180 dup2(pipes[0], STDIN_FILENO);
1181 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +00001182 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001183 LOGINFO("execlp pigz ERROR!\n");
1184 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001185 _exit(-1);
1186 }
1187 } else {
1188 // Parent
1189 close(pipes[0]); // Close pipes not used by parent
1190 close(pipes[1]);
1191 close(pipes[3]);
1192 fd = pipes[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001193 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 +00001194 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001195 LOGINFO("tar_fdopen failed\n");
1196 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001197 return -1;
1198 }
1199 }
1200 }
bigbiffce8f83c2015-12-12 18:30:21 -05001201 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001202 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001203 int oaesfd[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001204 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001205 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001206 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001207 return -1;
1208 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001209
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001210 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001211 LOGINFO("Error creating pipe\n");
1212 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001213 close(input_fd);
1214 return -1;
1215 }
1216
Dees_Troy83bd4832013-05-04 12:39:56 +00001217 oaes_pid = fork();
1218 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001219 LOGINFO("fork() failed\n");
1220 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001221 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001222 close(oaesfd[0]);
1223 close(oaesfd[1]);
1224 return -1;
1225 } else if (oaes_pid == 0) {
1226 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001227 dup2(oaesfd[1], STDOUT_FILENO); // remap stdout
1228 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001229 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001230 LOGINFO("execlp openaes ERROR!\n");
1231 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001232 _exit(-1);
1233 }
1234 } else {
1235 // Parent
1236 close(oaesfd[1]); // close parent output
1237 fd = oaesfd[0]; // copy parent input
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001238 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 +00001239 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001240 LOGINFO("tar_fdopen failed\n");
1241 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001242 return -1;
1243 }
1244 }
bigbiffce8f83c2015-12-12 18:30:21 -05001245 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001246 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001247
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -04001248 LOGINFO("Opening gzip compressed tar...\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001249 if (part_settings->adbbackup) {
1250 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001251 input_fd = open(TW_ADB_RESTORE, O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001252 }
1253 else
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001254 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001255
Dees Troy9d723272014-04-07 17:13:10 +00001256 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001257 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001258 return -1;
1259 }
bigbiffce8f83c2015-12-12 18:30:21 -05001260
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001261 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001262 LOGINFO("Error creating pipe\n");
1263 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001264 close(input_fd);
1265 return -1;
1266 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001267
1268 pigz_pid = fork();
1269 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001270 LOGINFO("fork() failed\n");
1271 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001272 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001273 close(pigzfd[0]);
1274 close(pigzfd[1]);
1275 return -1;
1276 } else if (pigz_pid == 0) {
1277 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001278 dup2(pigzfd[1], STDOUT_FILENO); // remap stdout
1279 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001280 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001281 LOGINFO("execlp pigz ERROR!\n");
Ethan Yonker74db1572015-10-28 12:44:49 -05001282 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001283 _exit(-1);
1284 }
1285 } else {
1286 // Parent
1287 close(pigzfd[1]); // close parent output
1288 fd = pigzfd[0]; // copy parent input
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001289 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 +00001290 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001291 LOGINFO("tar_fdopen failed\n");
1292 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001293 return -1;
1294 }
1295 }
bigbiffce8f83c2015-12-12 18:30:21 -05001296 } else {
1297 if (part_settings->adbbackup) {
1298 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1299 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001300 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 -05001301 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1302 gui_err("restore_error=Error during restore process.");
1303 return -1;
1304 }
1305 }
1306 else {
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001307 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 -05001308 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1309 gui_err("restore_error=Error during restore process.");
1310 return -1;
1311 }
1312 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001313 }
1314 return 0;
1315}
1316
1317string twrpTar::Strip_Root_Dir(string Path) {
1318 string temp;
1319 size_t slash;
1320
1321 if (Path.substr(0, 1) == "/")
1322 temp = Path.substr(1, Path.size() - 1);
1323 else
1324 temp = Path;
1325 slash = temp.find("/");
1326 if (slash == string::npos)
1327 return temp;
1328 else {
1329 string stripped;
1330
1331 stripped = temp.substr(slash, temp.size() - slash);
1332 return stripped;
1333 }
1334 return temp;
1335}
1336
1337int twrpTar::addFile(string fn, bool include_root) {
1338 char* charTarFile = (char*) fn.c_str();
1339 if (include_root) {
1340 if (tar_append_file(t, charTarFile, NULL) == -1)
1341 return -1;
1342 } else {
1343 string temp = Strip_Root_Dir(fn);
1344 char* charTarPath = (char*) temp.c_str();
1345 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1346 return -1;
1347 }
1348 return 0;
1349}
1350
Dees_Troy83bd4832013-05-04 12:39:56 +00001351int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001352 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001353 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001354 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001355 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001356 tar_close(t);
1357 return -1;
1358 }
1359 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001360 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001361 return -1;
1362 }
bigbiffce8f83c2015-12-12 18:30:21 -05001363 if (current_archive_type > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001364 int status;
1365 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1366 return -1;
1367 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1368 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001369 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001370 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001371 if (!part_settings->adbbackup) {
1372 if (use_compression && !use_encryption) {
1373 string gzname = tarfn + ".gz";
1374 if (TWFunc::Path_Exists(gzname)) {
1375 rename(gzname.c_str(), tarfn.c_str());
1376 }
Dees Troye0a433a2013-12-02 04:10:37 +00001377 }
bigbiffce8f83c2015-12-12 18:30:21 -05001378 if (TWFunc::Get_File_Size(tarfn) == 0) {
1379 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1380 return -1;
1381 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001382#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001383 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001384#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001385 }
1386 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001387#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001388 if (!twadbbu::Write_TWEOF())
1389 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001390#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001391 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001392 if (input_fd >= 0)
1393 close(input_fd);
1394 if (output_fd >= 0)
1395 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001396 return 0;
1397}
1398
1399int twrpTar::removeEOT(string tarFile) {
1400 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001401 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001402 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001403 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001404 tar_skip_regfile(t);
1405 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001406 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001407 if (tar_close(t) == -1)
1408 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001409 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001410 return -1;
1411 return 0;
1412}
1413
n0d33b511632013-03-06 21:14:15 +02001414int twrpTar::entryExists(string entry) {
1415 char* searchstr = (char*)entry.c_str();
1416 int ret;
1417
bigbiffce8f83c2015-12-12 18:30:21 -05001418 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001419
Dees_Troy83bd4832013-05-04 12:39:56 +00001420 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001421 ret = 0;
1422 else
1423 ret = tar_find(t, searchstr);
1424
Dees_Troy83bd4832013-05-04 12:39:56 +00001425 if (closeTar() != 0)
1426 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001427
1428 return ret;
1429}
1430
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001431unsigned long long twrpTar::get_size() {
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04001432 if (part_settings->adbbackup || TWFunc::Path_Exists(tarfn)) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001433 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001434 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001435 } else {
1436 LOGINFO("Multiple archives\n");
1437 string temp;
1438 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001439 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001440 unsigned long long total_restore_size = 0;
1441
1442 basefn = tarfn;
1443 temp = basefn + "%i%02i";
1444 tarfn += "000";
1445 thread_id = 0;
1446 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001447 if (!part_settings->adbbackup) {
1448 if (!TWFunc::Path_Exists(actual_filename)) {
1449 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1450 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001451 }
bigbiffce8f83c2015-12-12 18:30:21 -05001452 for (int i = 0; i < 9; i++) {
1453 archive_count = 0;
1454 sprintf(actual_filename, temp.c_str(), i, archive_count);
1455 while (TWFunc::Path_Exists(actual_filename)) {
1456 total_restore_size += uncompressedSize(actual_filename);
1457 archive_count++;
1458 if (archive_count > 99)
1459 break;
1460 sprintf(actual_filename, temp.c_str(), i, archive_count);
1461 }
1462 }
1463 #ifndef BUILD_TWRPTAR_MAIN
1464 if (!part_settings->adbbackup) {
1465 InfoManager backup_info(tarfn + ".info");
1466 backup_info.SetValue("backup_size", total_restore_size);
1467 backup_info.SetValue("backup_type", current_archive_type);
1468 backup_info.SaveValues();
1469 }
1470 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001471 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001472 return total_restore_size;
1473 }
1474 return 0;
1475}
1476
bigbiffce8f83c2015-12-12 18:30:21 -05001477unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001478 unsigned long long total_size = 0;
1479 string Tar, Command, result;
1480 vector<string> split;
1481
bigbiffce8f83c2015-12-12 18:30:21 -05001482 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1483 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001484 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001485 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001486 // Compressed
1487 Command = "pigz -l '" + filename + "'";
1488 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1489 we get the uncompressed size at once. */
bigbiffad58e1b2020-07-06 20:24:34 -04001490 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001491 if (!result.empty()) {
1492 /* Expected output:
1493 compressed original reduced name
1494 95855838 179403776 -1.3% data.yaffs2.win
1495 ^
1496 split[5]
1497 */
1498 split = TWFunc::split_string(result, ' ', true);
1499 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001500 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001501 }
bigbiffce8f83c2015-12-12 18:30:21 -05001502 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001503 // File is encrypted and may be compressed
1504 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001505 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001506 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001507 total_size = TWFunc::Get_File_Size(filename);
1508 } else if (ret == 1) {
1509 LOGERR("Decrypted file is not in tar format.\n");
1510 total_size = TWFunc::Get_File_Size(filename);
1511 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001512 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1513 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1514 we get the uncompressed size at once. */
bigbiffad58e1b2020-07-06 20:24:34 -04001515 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001516 if (!result.empty()) {
1517 LOGINFO("result was: '%s'\n", result.c_str());
1518 /* Expected output:
1519 compressed original reduced name
1520 95855838 179403776 -1.3% data.yaffs2.win
1521 ^
1522 split[5]
1523 */
1524 split = TWFunc::split_string(result, ' ', true);
1525 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001526 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001527 }
1528 } else {
1529 total_size = TWFunc::Get_File_Size(filename);
1530 }
1531 }
1532
1533 return total_size;
1534}
1535
Dees_Troye34c1332013-02-06 19:13:00 +00001536extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1537 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001538}
Ethan Yonker472f5062016-02-25 13:47:30 -06001539
1540extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1541 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1542}