blob: 71a5b1519f598f7893fd8db7983e09a3b825d93a [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"
bigbiff7ba75002020-04-11 20:47:09 -040060#endif
61#endif
62
bigbiff7ba75002020-04-11 20:47:09 -040063#ifdef USE_FSCRYPT
64#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR | TAR_STORE_FSCRYPT_POL
65#else
Ethan Yonker8d039f72017-02-03 14:26:15 -060066#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_POSIX_CAP | TAR_STORE_ANDROID_USER_XATTR
Ethan Yonker79f88bd2016-12-09 14:52:12 -060067#endif
68
bigbiff bigbiff9c754052013-01-09 09:09:08 -050069using namespace std;
70
Dees_Troy83bd4832013-05-04 12:39:56 +000071twrpTar::twrpTar(void) {
72 use_encryption = 0;
73 userdata_encryption = 0;
74 use_compression = 0;
75 split_archives = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +000076 pigz_pid = 0;
77 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000078 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060079 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000080 include_root_dir = true;
Ethan Yonkerf1179622016-08-25 15:32:21 -050081 tar_type.openfunc = open;
82 tar_type.closefunc = close;
83 tar_type.readfunc = read;
Ethan Yonkerea2fcf02016-09-12 16:07:19 -050084 input_fd = -1;
85 output_fd = -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -060086 backup_exclusions = NULL;
bigbiffa957f072021-03-07 18:20:29 -050087
bigbiff7ba75002020-04-11 20:47:09 -040088#ifdef USE_FSCRYPT
89 fscrypt_set_mode();
bigbiff7ba75002020-04-11 20:47:09 -040090#endif
Dees_Troy83bd4832013-05-04 12:39:56 +000091}
92
93twrpTar::~twrpTar(void) {
94 // Do nothing
95}
96
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050097void twrpTar::setfn(string fn) {
98 tarfn = fn;
99}
100
101void twrpTar::setdir(string dir) {
102 tardir = dir;
103}
104
Dees Troye0a433a2013-12-02 04:10:37 +0000105void twrpTar::setsize(unsigned long long backup_size) {
106 Total_Backup_Size = backup_size;
107}
108
Ethan Yonker87af5632014-02-10 11:56:35 -0600109void twrpTar::setpassword(string pass) {
110 password = pass;
111}
112
bigbiff7abc5fe2015-01-17 16:53:12 -0500113void twrpTar::Signal_Kill(int signum) {
114 _exit(255);
115}
116
bigbiffce8f83c2015-12-12 18:30:21 -0500117void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
118 current_archive_type = archive_type;
119}
120
121int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000122 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600123 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500124
125 file_count = 0;
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600126 if (backup_exclusions == NULL) {
127 LOGINFO("backup_exclusions is NULL\n");
128 return -1;
129 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500130
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600131#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500132 if (part_settings->adbbackup) {
133 std::string Backup_FileName(tarfn);
134 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
135 return -1;
136 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600137#endif
bigbiffce8f83c2015-12-12 18:30:21 -0500138
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500139 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500140 LOGINFO("Error creating progress tracking pipe\n");
141 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500142 return -1;
143 }
bigbiffce8f83c2015-12-12 18:30:21 -0500144 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000145 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500146 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500147 close(progress_pipe[0]);
148 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500149 return -1;
150 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500151
bigbiffce8f83c2015-12-12 18:30:21 -0500152 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500153 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500154 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500155 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500156 close(progress_pipe[0]);
157 progress_pipe_fd = progress_pipe[1];
158
Dees_Troy83bd4832013-05-04 12:39:56 +0000159 if (use_encryption || userdata_encryption) {
160 LOGINFO("Using encryption\n");
161 DIR* d;
162 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200163 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
164 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000165 int item_len, ret, thread_error = 0;
166 std::vector<TarListStruct> RegularList;
167 std::vector<TarListStruct> EncryptList;
168 string FileName;
169 struct TarListStruct TarItem;
170 twrpTar reg, enc[9];
171 struct stat st;
172 pthread_t enc_thread[9];
173 pthread_attr_t tattr;
174 void *thread_return;
175
176 core_count = sysconf(_SC_NPROCESSORS_CONF);
177 if (core_count > 8)
178 core_count = 8;
that2252d242015-04-03 22:33:04 +0200179 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000180 Archive_Current_Size = 0;
181
182 d = opendir(tardir.c_str());
183 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500184 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500185 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000186 _exit(-1);
187 }
188 // Figure out the size of all data to be encrypted and create a list of unencrypted files
189 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500190 FileName = tardir + "/" + de->d_name;
191
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600192 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000193 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500194 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000195 item_len = strlen(de->d_name);
196 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 -0500197 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
198 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500199 LOGINFO("Error in Generate_TarList with regular list!\n");
200 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000201 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500202 close(progress_pipe_fd);
203 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000204 _exit(-1);
205 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500206 file_count = (unsigned long long)(ret);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600207 regular_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000208 } else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600209 encrypt_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000210 }
211 } else if (de->d_type == DT_REG) {
212 stat(FileName.c_str(), &st);
213 encrypt_size += (unsigned long long)(st.st_size);
214 }
215 }
216 closedir(d);
217
218 target_size = encrypt_size / core_count;
219 target_size++;
220 LOGINFO(" Unencrypted size: %llu\n", regular_size);
221 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
222 LOGINFO(" Target size : %llu\n", target_size);
223 if (!userdata_encryption) {
224 enc_thread_id = 0;
225 start_thread_id = 0;
226 core_count--;
227 }
228 Archive_Current_Size = 0;
229
230 d = opendir(tardir.c_str());
231 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500232 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500233 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000234 _exit(-1);
235 }
236 // Divide up the encrypted file list for threading
237 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500238 FileName = tardir + "/" + de->d_name;
239
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600240 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000241 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500242 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 item_len = strlen(de->d_name);
244 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
245 // Do nothing, we added these to RegularList earlier
246 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500247 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500248 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
249 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500250 LOGINFO("Error in Generate_TarList with encrypted list!\n");
251 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000252 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500253 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000254 _exit(-1);
255 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500256 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000257 }
258 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
259 stat(FileName.c_str(), &st);
260 if (de->d_type == DT_REG)
261 Archive_Current_Size += (unsigned long long)(st.st_size);
262 TarItem.fn = FileName;
263 TarItem.thread_id = enc_thread_id;
264 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500265 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000266 }
267 }
268 closedir(d);
269 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500270 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 -0500271 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500272 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500273 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000274 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500275 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500276 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500277 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000278 }
279
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500280 // Send file count to parent
281 write(progress_pipe_fd, &file_count, sizeof(file_count));
282 // Send backup size to parent
283 total_size = regular_size + encrypt_size;
284 write(progress_pipe_fd, &total_size, sizeof(total_size));
285
Dees_Troy83bd4832013-05-04 12:39:56 +0000286 if (userdata_encryption) {
287 // Create a backup of unencrypted data
288 reg.setfn(tarfn);
289 reg.ItemList = &RegularList;
290 reg.thread_id = 0;
291 reg.use_encryption = 0;
292 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000293 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500294 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500295 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000296 LOGINFO("Creating unencrypted backup...\n");
297 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500298 LOGINFO("Error creating unencrypted backup.\n");
299 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500300 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000301 _exit(-1);
302 }
303 }
304
305 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500306 LOGINFO("Unable to pthread_attr_init\n");
307 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500308 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000309 _exit(-1);
310 }
311 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500312 LOGINFO("Error setting pthread_attr_setdetachstate\n");
313 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500314 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000315 _exit(-1);
316 }
317 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500318 LOGINFO("Error setting pthread_attr_setscope\n");
319 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500320 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000321 _exit(-1);
322 }
323 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
324 LOGERR("Error setting pthread_attr_setstacksize\n");
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100325 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000326 _exit(-1);
327 }*/
328
329 // Create threads for the divided up encryption lists
330 for (i = start_thread_id; i <= core_count; i++) {
331 enc[i].setdir(tardir);
332 enc[i].setfn(tarfn);
333 enc[i].ItemList = &EncryptList;
334 enc[i].thread_id = i;
335 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500336 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000337 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000338 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500339 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500340 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000341 LOGINFO("Start encryption thread %i\n", i);
342 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
343 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500344 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 +0000345 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500346 LOGINFO("Error creating encrypted backup %i.\n", i);
347 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500348 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000349 _exit(-1);
350 } else {
351 enc[i].thread_id = i + 1;
352 }
353 }
354 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
355 }
356 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500357 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000358 }
359 for (i = start_thread_id; i <= core_count; i++) {
360 if (enc[i].thread_id == i) {
361 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500362 LOGINFO("Error joining thread %i\n", i);
363 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500364 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000365 _exit(-1);
366 } else {
367 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200368 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000369 if (ret != 0) {
370 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500371 LOGINFO("Thread %i returned an error %i.\n", i, ret);
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 }
376 }
377 } else {
378 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
379 }
380 }
381 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500382 LOGINFO("Error returned by one or more threads.\n");
383 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500384 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000385 _exit(-1);
386 }
387 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500388 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000389 _exit(0);
390 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500391 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000392 std::vector<TarListStruct> FileList;
393 unsigned thread_id = 0;
394 unsigned long long target_size = 0;
395 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500396 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000397
398 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500399 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
400 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500401 LOGINFO("Error in Generate_TarList!\n");
402 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500403 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000404 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000405 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500406 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000407 // Create a backup
408 reg.setfn(tarfn);
409 reg.ItemList = &FileList;
410 reg.thread_id = 0;
411 reg.use_encryption = 0;
412 reg.use_compression = use_compression;
413 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500414 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500415 reg.part_settings = part_settings;
416 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500417 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000418 reg.split_archives = 1;
419 } else {
420 reg.split_archives = 0;
421 }
422 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500423 write(progress_pipe_fd, &file_count, sizeof(file_count));
424 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000425 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500426 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500427 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000428 _exit(-1);
429 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500430 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000431 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000432 }
433 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500434 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600435 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500436 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500437
438 // Parent closes output side
439 close(progress_pipe[1]);
440
441 // Read progress data from children
442 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
443 if (first_data == 0) {
444 // First incoming data is the file count
445 file_count = fs;
446 if (file_count == 0) file_count = 1; // prevent division by 0 below
447 first_data = 1;
448 } else if (first_data == 1) {
449 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500450 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500451 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500452 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600453 if (fs > 0) {
454 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500455 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600456 } else { // fs == 0 increments the file counter
457 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500458 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600459 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500460 }
461 }
462 close(progress_pipe[0]);
463#ifndef BUILD_TWRPTAR_MAIN
464 DataManager::SetValue("tw_file_progress", "");
465 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500466 part_settings->progress->DisplayFileCount(false);
467 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500468
bigbiffce8f83c2015-12-12 18:30:21 -0500469 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400470 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500471 backup_info.SetValue("backup_size", size_backup);
472 if (use_compression && use_encryption)
473 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
474 else if (use_encryption)
475 backup_info.SetValue("backup_type", ENCRYPTED);
476 else if (use_compression)
477 backup_info.SetValue("backup_type", COMPRESSED);
478 else
479 backup_info.SetValue("backup_type", UNCOMPRESSED);
480 backup_info.SetValue("file_count", files_backup);
481 backup_info.SaveValues();
482 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500483#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500484 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500485 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500486 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500487 return 0;
488}
489
bigbiffce8f83c2015-12-12 18:30:21 -0500490int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000491 int status = 0;
Matt Mower23d8aae2017-01-06 14:30:33 -0600492 pid_t tar_fork_pid;
493 int progress_pipe[2];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500494
495 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500496 LOGINFO("Error creating progress tracking pipe\n");
497 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500498 return -1;
499 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000500
bigbiff7abc5fe2015-01-17 16:53:12 -0500501 tar_fork_pid = fork();
502 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000503 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500504 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000505 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500506 close(progress_pipe[0]);
507 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500508 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000509 LOGINFO("Single archive\n");
510 if (extract() != 0)
511 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500512 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000513 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500514 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000515 } else {
516 LOGINFO("Multiple archives\n");
517 string temp;
518 char actual_filename[255];
519 twrpTar tars[9];
520 pthread_t tar_thread[9];
521 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500522 unsigned thread_count = 0, i, start_thread_id = 1;
523 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000524 void *thread_return;
525
526 basefn = tarfn;
527 temp = basefn + "%i%02i";
528 tarfn += "000";
529 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500530 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
531 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500532 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 _exit(-1);
534 }
535 if (TWFunc::Get_File_Type(tarfn) != 2) {
536 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
537 tars[0].basefn = basefn;
538 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500539 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500540 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000541 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500542 LOGINFO("Error extracting split archive.\n");
543 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500544 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000545 _exit(-1);
546 }
547 } else {
548 start_thread_id = 0;
549 }
550 // Start threading encrypted restores
551 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500552 LOGINFO("Unable to pthread_attr_init\n");
553 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500554 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000555 _exit(-1);
556 }
557 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500558 LOGINFO("Error setting pthread_attr_setdetachstate\n");
559 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500560 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000561 _exit(-1);
562 }
563 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500564 LOGINFO("Error setting pthread_attr_setscope\n");
565 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500566 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000567 _exit(-1);
568 }
569 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
570 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500571 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000572 _exit(-1);
573 }*/
574 for (i = start_thread_id; i < 9; i++) {
575 sprintf(actual_filename, temp.c_str(), i, 0);
576 if (TWFunc::Path_Exists(actual_filename)) {
577 thread_count++;
578 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500579 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000580 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500581 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500582 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000583 LOGINFO("Creating extract thread ID %i\n", i);
584 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
585 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500586 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 +0000587 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500588 LOGINFO("Error extracting backup in thread %i.\n", i);
589 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500590 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000591 _exit(-1);
592 } else {
593 tars[i].thread_id = i + 1;
594 }
595 }
596 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
597 } else {
598 break;
599 }
600 }
601 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
602 if (tars[i].thread_id == i) {
603 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500604 LOGINFO("Error joining thread %i\n", i);
605 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500606 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000607 _exit(-1);
608 } else {
609 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200610 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000611 if (ret != 0) {
612 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500613 LOGINFO("Thread %i returned an error %i.\n", i, ret);
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 }
618 }
619 } else {
620 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
621 }
622 }
623 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500624 LOGINFO("Error returned by one or more threads.\n");
625 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500626 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000627 _exit(-1);
628 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500629 LOGINFO("Finished encrypted restore.\n");
630 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000631 _exit(0);
632 }
633 }
634 else // parent process
635 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600636 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500637
638 // Parent closes output side
639 close(progress_pipe[1]);
640
641 // Read progress data from children
642 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
643 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500644 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500645 }
646 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500647 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500648
bigbiff7abc5fe2015-01-17 16:53:12 -0500649 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000650 return -1;
651 }
652 }
653 else // fork has failed
654 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500655 close(progress_pipe[0]);
656 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000657 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500658 return -1;
659 }
660 return 0;
661}
662
Dees_Troy83bd4832013-05-04 12:39:56 +0000663int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
664 DIR* d;
665 struct dirent* de;
666 struct stat st;
667 string FileName;
668 struct TarListStruct TarItem;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500669 int ret, file_count;
670 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000671
Dees_Troy83bd4832013-05-04 12:39:56 +0000672 d = opendir(Path.c_str());
673 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500674 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000675 closedir(d);
676 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500677 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000678 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500679 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500680
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600681 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000682 continue;
683 TarItem.fn = FileName;
684 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500685 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000686 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500687 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
688 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500689 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500690 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
692 stat(FileName.c_str(), &st);
693 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500694 if (de->d_type == DT_REG) {
695 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000696 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500697 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000698 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
699 *thread_id = *thread_id + 1;
700 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500701 }
702 }
703 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000704 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500705 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500706}
707
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500708int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000709 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000710 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500711 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500712 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500713 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
714 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500715 return -1;
716 }
717 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500718 LOGINFO("Unable to close tar file\n");
719 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500720 return -1;
721 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600722#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500723 if (part_settings->adbbackup) {
724 if (!twadbbu::Write_TWEOF())
725 return -1;
726 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600727#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500728 return 0;
729}
730
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500731int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500732 if (!part_settings->adbbackup) {
733 LOGINFO("Setting archive type\n");
734 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
735 }
736 else {
737 if (part_settings->adb_compression == 1)
738 current_archive_type = COMPRESSED;
739 else
740 current_archive_type = UNCOMPRESSED;
741 }
n0d33b511632013-03-06 21:14:15 +0200742
bigbiffce8f83c2015-12-12 18:30:21 -0500743 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500744 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000745 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000746 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500747 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500748 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600749 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000750 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500751 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000752 return -1;
753 }
754 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500755 LOGINFO("Decrypted file is not in tar format.\n");
756 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000757 return -1;
758 }
759 if (ret == 3) {
760 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500761 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000762 } else
763 LOGINFO("Extracting encrypted tar.\n");
764 return extractTar();
765 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000766 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500767 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500768 }
769}
770
Dees Troye0a433a2013-12-02 04:10:37 +0000771int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000772 struct stat st;
773 char buf[PATH_MAX];
774 int list_size = TarList->size(), i = 0, archive_count = 0;
775 string temp;
776 char actual_filename[PATH_MAX];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500777 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000778
Dees Troye0a433a2013-12-02 04:10:37 +0000779 if (split_archives) {
780 basefn = tarfn;
781 temp = basefn + "%i%02i";
782 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
783 tarfn = actual_filename;
784 include_root_dir = true;
785 } else {
786 include_root_dir = false;
787 }
bigbiffce8f83c2015-12-12 18:30:21 -0500788
789 if (part_settings->adbbackup)
790 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
791 else
792 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
793
Dees_Troy83bd4832013-05-04 12:39:56 +0000794 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500795 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
796 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000797 return -2;
798 }
799 Archive_Current_Size = 0;
800
801 while (i < list_size) {
802 if (TarList->at(i).thread_id == thread_id) {
803 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400804 lstat(buf, &st);
805 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500806 fs = (unsigned long long)(st.st_size);
807 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000808 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500809 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
810 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000811 return -3;
812 }
813 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500814 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000815 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500816 LOGINFO("Too many archives for thread %i\n", thread_id);
817 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000818 return -4;
819 }
820 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
821 tarfn = actual_filename;
822 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500823 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
824 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000825 return -2;
826 }
827 Archive_Current_Size = 0;
828 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500829 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600830 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500831 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000832 }
Dees Troye0a433a2013-12-02 04:10:37 +0000833 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
834 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500835 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
836 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000837 return -1;
838 }
839 }
840 i++;
841 }
842 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500843 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
844 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000845 return -3;
846 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600847 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000848 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500849}
850
Dees_Troy83bd4832013-05-04 12:39:56 +0000851void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000852 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600853 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000854 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
855 return (void*)-2;
856 }
857 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
858 return (void*)0;
859}
860
861void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000862 twrpTar* threadTar = (twrpTar*) cookie;
863 int archive_count = 0;
864 string temp = threadTar->basefn + "%i%02i";
865 char actual_filename[255];
866 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
867 while (TWFunc::Path_Exists(actual_filename)) {
868 threadTar->tarfn = actual_filename;
869 if (threadTar->extract() != 0) {
870 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
871 return (void*)-2;
872 }
873 archive_count++;
874 if (archive_count > 99)
875 break;
876 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
877 }
878 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
879 return (void*)0;
880}
881
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500882int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
883 char* charTarFile = (char*) fn.c_str();
884
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100885 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 -0500886 return -1;
887 removeEOT(charTarFile);
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100888 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 -0500889 return -1;
890 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500891 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500892 if (tar_append_file(t, file, file) == -1)
893 return -1;
894 }
895 if (tar_append_eof(t) == -1)
896 return -1;
897 if (tar_close(t) == -1)
898 return -1;
899 return 0;
900}
901
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500902int twrpTar::createTar() {
903 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000904 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500905
Dees_Troy83bd4832013-05-04 12:39:56 +0000906 if (use_encryption && use_compression) {
907 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500908 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000909 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000910 int i, pipes[4];
911
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100912 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500913 LOGINFO("Error creating first pipe\n");
914 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500915 return -1;
916 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100917 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500918 LOGINFO("Error creating second pipe\n");
919 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500920 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000921 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100922 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 +0000923 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500924 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000925 for (i = 0; i < 4; i++)
926 close(pipes[i]); // close all
927 return -1;
928 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000929 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400930
Dees_Troy83bd4832013-05-04 12:39:56 +0000931 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500932 LOGINFO("pigz fork() failed\n");
933 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000934 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000935 for (i = 0; i < 4; i++)
936 close(pipes[i]); // close all
937 return -1;
938 } else if (pigz_pid == 0) {
939 // pigz Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100940 dup2(pipes[0], STDIN_FILENO);
941 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +0000942 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500943 LOGINFO("execlp pigz ERROR!\n");
944 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000945 _exit(-1);
946 }
947 } else {
948 // Parent
949 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400950
Dees_Troy83bd4832013-05-04 12:39:56 +0000951 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500952 LOGINFO("openaes fork() failed\n");
953 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000954 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000955 for (i = 0; i < 4; i++)
956 close(pipes[i]); // close all
957 return -1;
958 } else if (oaes_pid == 0) {
959 // openaes Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100960 dup2(pipes[2], STDIN_FILENO);
961 dup2(output_fd, STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -0600962 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500963 LOGINFO("execlp openaes ERROR!\n");
964 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000965 _exit(-1);
966 }
967 } else {
968 // Parent
969 close(pipes[0]);
970 close(pipes[2]);
971 close(pipes[3]);
972 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600973 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500974 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100975 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 +0000976 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500977 LOGINFO("tar_fdopen failed\n");
978 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000979 return -1;
980 }
981 return 0;
982 }
983 }
984 } else if (use_compression) {
985 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -0500986 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000987 LOGINFO("Using compression...\n");
988 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -0500989 if (part_settings->adbbackup) {
990 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
991 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
992 }
993 else {
Fabrice Bellet72bcc202019-12-15 17:49:18 +0100994 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 -0500995 }
Dees Troy9d723272014-04-07 17:13:10 +0000996 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500997 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000998 return -1;
999 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001000
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001001 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001002 LOGINFO("Error creating pipe\n");
1003 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001004 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001005 return -1;
1006 }
1007 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001008
Dees_Troy83bd4832013-05-04 12:39:56 +00001009 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001010 LOGINFO("fork() failed\n");
1011 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001012 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001013 close(pigzfd[0]);
1014 close(pigzfd[1]);
1015 return -1;
1016 } else if (pigz_pid == 0) {
1017 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001018 dup2(pigzfd[0], STDIN_FILENO); // remap stdin
1019 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001020 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001021 LOGINFO("execlp pigz ERROR!\n");
1022 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001023 _exit(-1);
1024 }
1025 } else {
1026 // Parent
1027 close(pigzfd[0]); // close parent input
1028 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001029 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001030 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001031 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 +00001032 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001033 LOGINFO("tar_fdopen failed\n");
1034 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001035 return -1;
1036 }
1037 }
1038 } else if (use_encryption) {
1039 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001040 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001041 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001042 int oaesfd[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001043 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 +00001044 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001045 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001046 return -1;
1047 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001048 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001049 LOGINFO("Error creating pipe\n");
1050 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001051 close(output_fd);
1052 return -1;
1053 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001055
Dees_Troy83bd4832013-05-04 12:39:56 +00001056 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001057 LOGINFO("fork() failed\n");
1058 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001059 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001060 close(oaesfd[0]);
1061 close(oaesfd[1]);
1062 return -1;
1063 } else if (oaes_pid == 0) {
1064 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001065 dup2(oaesfd[0], STDIN_FILENO); // remap stdin
1066 dup2(output_fd, STDOUT_FILENO); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001067 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001068 LOGINFO("execlp openaes ERROR!\n");
1069 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001070 _exit(-1);
1071 }
1072 } else {
1073 // Parent
1074 close(oaesfd[0]); // close parent input
1075 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001076 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001077 tar_type.writefunc = write_tar_no_buffer;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001078 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 +00001079 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001080 LOGINFO("tar_fdopen failed\n");
1081 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001082 return -1;
1083 }
1084 return 0;
1085 }
1086 } else {
1087 // Not compressed or encrypted
nkk71d59d02e2017-06-29 15:16:23 +03001088 current_archive_type = UNCOMPRESSED;
Ethan Yonker472f5062016-02-25 13:47:30 -06001089 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001090 if (part_settings->adbbackup) {
1091 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001092 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001093 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001094 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 -05001095 close(output_fd);
1096 LOGERR("tar_fdopen failed\n");
1097 return -1;
1098 }
1099 }
1100 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001101 tar_type.writefunc = write_tar;
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001102 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 -05001103 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1104 gui_err("backup_error=Error creating backup.");
1105 return -1;
1106 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001107 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001108 }
1109 return 0;
1110}
1111
Dees_Troy83bd4832013-05-04 12:39:56 +00001112int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001113 char* charRootDir = (char*) tardir.c_str();
1114 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001115 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001116
bigbiffce8f83c2015-12-12 18:30:21 -05001117 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001118 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001119 int i, pipes[4];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001120 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001121 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001122 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001123 return -1;
1124 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001125
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001126 if (pipe2(pipes, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001127 LOGINFO("Error creating first pipe\n");
1128 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001129 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001130 return -1;
1131 }
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001132 if (pipe2(pipes + 2, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001133 LOGINFO("Error creating second pipe\n");
1134 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001135 close(pipes[0]);
1136 close(pipes[1]);
1137 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001138 return -1;
1139 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001140 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001141
Dees_Troy83bd4832013-05-04 12:39:56 +00001142 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001143 LOGINFO("pigz fork() failed\n");
1144 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001145 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001146 for (i = 0; i < 4; i++)
1147 close(pipes[i]); // close all
1148 return -1;
1149 } else if (oaes_pid == 0) {
1150 // openaes Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001151 dup2(input_fd, STDIN_FILENO);
1152 dup2(pipes[1], STDOUT_FILENO);
Ethan Yonker87af5632014-02-10 11:56:35 -06001153 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001154 LOGINFO("execlp openaes ERROR!\n");
1155 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001156 _exit(-1);
1157 }
1158 } else {
1159 // Parent
1160 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001161
Dees_Troy83bd4832013-05-04 12:39:56 +00001162 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001163 LOGINFO("openaes fork() failed\n");
1164 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001165 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001166 for (i = 0; i < 4; i++)
1167 close(pipes[i]); // close all
1168 return -1;
1169 } else if (pigz_pid == 0) {
1170 // pigz Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001171 dup2(pipes[0], STDIN_FILENO);
1172 dup2(pipes[3], STDOUT_FILENO);
Dees_Troy83bd4832013-05-04 12:39:56 +00001173 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001174 LOGINFO("execlp pigz ERROR!\n");
1175 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001176 _exit(-1);
1177 }
1178 } else {
1179 // Parent
1180 close(pipes[0]); // Close pipes not used by parent
1181 close(pipes[1]);
1182 close(pipes[3]);
1183 fd = pipes[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001184 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 +00001185 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001186 LOGINFO("tar_fdopen failed\n");
1187 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001188 return -1;
1189 }
1190 }
1191 }
bigbiffce8f83c2015-12-12 18:30:21 -05001192 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001193 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001194 int oaesfd[2];
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001195 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001196 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001197 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001198 return -1;
1199 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001200
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001201 if (pipe2(oaesfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001202 LOGINFO("Error creating pipe\n");
1203 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001204 close(input_fd);
1205 return -1;
1206 }
1207
Dees_Troy83bd4832013-05-04 12:39:56 +00001208 oaes_pid = fork();
1209 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001210 LOGINFO("fork() failed\n");
1211 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001212 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001213 close(oaesfd[0]);
1214 close(oaesfd[1]);
1215 return -1;
1216 } else if (oaes_pid == 0) {
1217 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001218 dup2(oaesfd[1], STDOUT_FILENO); // remap stdout
1219 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001220 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001221 LOGINFO("execlp openaes ERROR!\n");
1222 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001223 _exit(-1);
1224 }
1225 } else {
1226 // Parent
1227 close(oaesfd[1]); // close parent output
1228 fd = oaesfd[0]; // copy parent input
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001229 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 +00001230 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001231 LOGINFO("tar_fdopen failed\n");
1232 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001233 return -1;
1234 }
1235 }
bigbiffce8f83c2015-12-12 18:30:21 -05001236 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001237 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001238
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -04001239 LOGINFO("Opening gzip compressed tar...\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001240 if (part_settings->adbbackup) {
1241 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001242 input_fd = open(TW_ADB_RESTORE, O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001243 }
1244 else
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001245 input_fd = open(tarfn.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE);
bigbiffce8f83c2015-12-12 18:30:21 -05001246
Dees Troy9d723272014-04-07 17:13:10 +00001247 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001248 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001249 return -1;
1250 }
bigbiffce8f83c2015-12-12 18:30:21 -05001251
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001252 if (pipe2(pigzfd, O_CLOEXEC) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001253 LOGINFO("Error creating pipe\n");
1254 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001255 close(input_fd);
1256 return -1;
1257 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001258
1259 pigz_pid = fork();
1260 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001261 LOGINFO("fork() failed\n");
1262 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001263 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001264 close(pigzfd[0]);
1265 close(pigzfd[1]);
1266 return -1;
1267 } else if (pigz_pid == 0) {
1268 // Child
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001269 dup2(pigzfd[1], STDOUT_FILENO); // remap stdout
1270 dup2(input_fd, STDIN_FILENO); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001271 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001272 LOGINFO("execlp pigz ERROR!\n");
Ethan Yonker74db1572015-10-28 12:44:49 -05001273 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001274 _exit(-1);
1275 }
1276 } else {
1277 // Parent
1278 close(pigzfd[1]); // close parent output
1279 fd = pigzfd[0]; // copy parent input
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001280 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 +00001281 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001282 LOGINFO("tar_fdopen failed\n");
1283 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001284 return -1;
1285 }
1286 }
bigbiffce8f83c2015-12-12 18:30:21 -05001287 } else {
1288 if (part_settings->adbbackup) {
1289 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1290 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001291 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 -05001292 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1293 gui_err("restore_error=Error during restore process.");
1294 return -1;
1295 }
1296 }
1297 else {
Fabrice Bellet72bcc202019-12-15 17:49:18 +01001298 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 -05001299 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1300 gui_err("restore_error=Error during restore process.");
1301 return -1;
1302 }
1303 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001304 }
1305 return 0;
1306}
1307
1308string twrpTar::Strip_Root_Dir(string Path) {
1309 string temp;
1310 size_t slash;
1311
1312 if (Path.substr(0, 1) == "/")
1313 temp = Path.substr(1, Path.size() - 1);
1314 else
1315 temp = Path;
1316 slash = temp.find("/");
1317 if (slash == string::npos)
1318 return temp;
1319 else {
1320 string stripped;
1321
1322 stripped = temp.substr(slash, temp.size() - slash);
1323 return stripped;
1324 }
1325 return temp;
1326}
1327
1328int twrpTar::addFile(string fn, bool include_root) {
1329 char* charTarFile = (char*) fn.c_str();
1330 if (include_root) {
1331 if (tar_append_file(t, charTarFile, NULL) == -1)
1332 return -1;
1333 } else {
1334 string temp = Strip_Root_Dir(fn);
1335 char* charTarPath = (char*) temp.c_str();
1336 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1337 return -1;
1338 }
1339 return 0;
1340}
1341
Dees_Troy83bd4832013-05-04 12:39:56 +00001342int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001343 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001344 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001345 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001346 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001347 tar_close(t);
1348 return -1;
1349 }
1350 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001351 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001352 return -1;
1353 }
bigbiffce8f83c2015-12-12 18:30:21 -05001354 if (current_archive_type > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001355 int status;
1356 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1357 return -1;
1358 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1359 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001360 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001361 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001362 if (!part_settings->adbbackup) {
1363 if (use_compression && !use_encryption) {
1364 string gzname = tarfn + ".gz";
1365 if (TWFunc::Path_Exists(gzname)) {
1366 rename(gzname.c_str(), tarfn.c_str());
1367 }
Dees Troye0a433a2013-12-02 04:10:37 +00001368 }
bigbiffce8f83c2015-12-12 18:30:21 -05001369 if (TWFunc::Get_File_Size(tarfn) == 0) {
1370 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1371 return -1;
1372 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001373#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001374 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001375#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001376 }
1377 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001378#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001379 if (!twadbbu::Write_TWEOF())
1380 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001381#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001382 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001383 if (input_fd >= 0)
1384 close(input_fd);
1385 if (output_fd >= 0)
1386 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001387 return 0;
1388}
1389
1390int twrpTar::removeEOT(string tarFile) {
1391 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001392 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001393 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001394 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001395 tar_skip_regfile(t);
1396 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001397 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001398 if (tar_close(t) == -1)
1399 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001400 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001401 return -1;
1402 return 0;
1403}
1404
n0d33b511632013-03-06 21:14:15 +02001405int twrpTar::entryExists(string entry) {
1406 char* searchstr = (char*)entry.c_str();
1407 int ret;
1408
bigbiffce8f83c2015-12-12 18:30:21 -05001409 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001410
Dees_Troy83bd4832013-05-04 12:39:56 +00001411 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001412 ret = 0;
1413 else
1414 ret = tar_find(t, searchstr);
1415
Dees_Troy83bd4832013-05-04 12:39:56 +00001416 if (closeTar() != 0)
1417 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001418
1419 return ret;
1420}
1421
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001422unsigned long long twrpTar::get_size() {
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -04001423 if (part_settings->adbbackup || TWFunc::Path_Exists(tarfn)) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001424 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001425 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001426 } else {
1427 LOGINFO("Multiple archives\n");
1428 string temp;
1429 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001430 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001431 unsigned long long total_restore_size = 0;
1432
1433 basefn = tarfn;
1434 temp = basefn + "%i%02i";
1435 tarfn += "000";
1436 thread_id = 0;
1437 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001438 if (!part_settings->adbbackup) {
1439 if (!TWFunc::Path_Exists(actual_filename)) {
1440 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1441 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001442 }
bigbiffce8f83c2015-12-12 18:30:21 -05001443 for (int i = 0; i < 9; i++) {
1444 archive_count = 0;
1445 sprintf(actual_filename, temp.c_str(), i, archive_count);
1446 while (TWFunc::Path_Exists(actual_filename)) {
1447 total_restore_size += uncompressedSize(actual_filename);
1448 archive_count++;
1449 if (archive_count > 99)
1450 break;
1451 sprintf(actual_filename, temp.c_str(), i, archive_count);
1452 }
1453 }
1454 #ifndef BUILD_TWRPTAR_MAIN
1455 if (!part_settings->adbbackup) {
1456 InfoManager backup_info(tarfn + ".info");
1457 backup_info.SetValue("backup_size", total_restore_size);
1458 backup_info.SetValue("backup_type", current_archive_type);
1459 backup_info.SaveValues();
1460 }
1461 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001462 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001463 return total_restore_size;
1464 }
1465 return 0;
1466}
1467
bigbiffce8f83c2015-12-12 18:30:21 -05001468unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001469 unsigned long long total_size = 0;
1470 string Tar, Command, result;
1471 vector<string> split;
1472
bigbiffce8f83c2015-12-12 18:30:21 -05001473 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1474 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001475 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001476 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001477 // Compressed
1478 Command = "pigz -l '" + filename + "'";
1479 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1480 we get the uncompressed size at once. */
bigbiffad58e1b2020-07-06 20:24:34 -04001481 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001482 if (!result.empty()) {
1483 /* Expected output:
1484 compressed original reduced name
1485 95855838 179403776 -1.3% data.yaffs2.win
1486 ^
1487 split[5]
1488 */
1489 split = TWFunc::split_string(result, ' ', true);
1490 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001491 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001492 }
bigbiffce8f83c2015-12-12 18:30:21 -05001493 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001494 // File is encrypted and may be compressed
1495 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001496 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001497 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001498 total_size = TWFunc::Get_File_Size(filename);
1499 } else if (ret == 1) {
1500 LOGERR("Decrypted file is not in tar format.\n");
1501 total_size = TWFunc::Get_File_Size(filename);
1502 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001503 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1504 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1505 we get the uncompressed size at once. */
bigbiffad58e1b2020-07-06 20:24:34 -04001506 TWFunc::Exec_Cmd(Command, result, false);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001507 if (!result.empty()) {
1508 LOGINFO("result was: '%s'\n", result.c_str());
1509 /* Expected output:
1510 compressed original reduced name
1511 95855838 179403776 -1.3% data.yaffs2.win
1512 ^
1513 split[5]
1514 */
1515 split = TWFunc::split_string(result, ' ', true);
1516 if (split.size() > 4)
Matt Mowera8a89d12016-12-30 18:10:37 -06001517 total_size = atoi(split[5].c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001518 }
1519 } else {
1520 total_size = TWFunc::Get_File_Size(filename);
1521 }
1522 }
1523
1524 return total_size;
1525}
1526
Dees_Troye34c1332013-02-06 19:13:00 +00001527extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1528 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001529}
Ethan Yonker472f5062016-02-25 13:47:30 -06001530
1531extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1532 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1533}