blob: 4f9b633036f05164082c79a1f2204117c68fd421 [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
Ethan Yonker472f5062016-02-25 13:47:30 -06003 Copyright 2013 to 2016 bigbiff/Dees_Troy TeamWin
Dees_Troye34c1332013-02-06 19:13:00 +00004 This file is part of TWRP/TeamWin Recovery Project.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05005
Dees_Troye34c1332013-02-06 19:13:00 +00006 TWRP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050010
Dees_Troye34c1332013-02-06 19:13:00 +000011 TWRP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050015
Dees_Troye34c1332013-02-06 19:13:00 +000016 You should have received a copy of the GNU General Public License
17 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050018*/
19
20extern "C" {
21 #include "libtar/libtar.h"
Dees_Troye34c1332013-02-06 19:13:00 +000022 #include "twrpTar.h"
23 #include "tarWrite.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050024}
25#include <sys/types.h>
26#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050027#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050028#include <string.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050032#include <iostream>
33#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050034#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000035#include <vector>
bigbiff7abc5fe2015-01-17 16:53:12 -050036#include <csignal>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050037#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040038#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050039#include <sys/mman.h>
bigbiffce8f83c2015-12-12 18:30:21 -050040#include <sys/ioctl.h>
41#include <zlib.h>
42#include <semaphore.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050043#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000044#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050045#include "variables.h"
bigbiffce8f83c2015-12-12 18:30:21 -050046#include "adbbu/libtwadbbu.hpp"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050047#include "twrp-functions.hpp"
Ethan Yonker472f5062016-02-25 13:47:30 -060048#include "gui/gui.hpp"
49#include "progresstracking.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050050#ifndef BUILD_TWRPTAR_MAIN
51#include "data.hpp"
52#include "infomanager.hpp"
Ethan Yonkerf1179622016-08-25 15:32:21 -050053#include "set_metadata.h"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050054#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050055
Ethan Yonker79f88bd2016-12-09 14:52:12 -060056#ifdef TW_INCLUDE_FBE
57#include "crypto/ext4crypt/ext4crypt_tar.h"
58#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX | TAR_STORE_EXT4_POL
59#else
60#define TWTAR_FLAGS TAR_GNU | TAR_STORE_SELINUX
61#endif
62
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063using namespace std;
64
Dees_Troy83bd4832013-05-04 12:39:56 +000065twrpTar::twrpTar(void) {
66 use_encryption = 0;
67 userdata_encryption = 0;
68 use_compression = 0;
69 split_archives = 0;
70 has_data_media = 0;
71 pigz_pid = 0;
72 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000073 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060074 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000075 include_root_dir = true;
Ethan Yonkerf1179622016-08-25 15:32:21 -050076 tar_type.openfunc = open;
77 tar_type.closefunc = close;
78 tar_type.readfunc = read;
Ethan Yonkerea2fcf02016-09-12 16:07:19 -050079 input_fd = -1;
80 output_fd = -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -060081 backup_exclusions = NULL;
Ethan Yonker79f88bd2016-12-09 14:52:12 -060082#ifdef TW_INCLUDE_FBE
83 e4crypt_set_mode();
84#endif
Dees_Troy83bd4832013-05-04 12:39:56 +000085}
86
87twrpTar::~twrpTar(void) {
88 // Do nothing
89}
90
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050091void twrpTar::setfn(string fn) {
92 tarfn = fn;
93}
94
95void twrpTar::setdir(string dir) {
96 tardir = dir;
97}
98
Dees Troye0a433a2013-12-02 04:10:37 +000099void twrpTar::setsize(unsigned long long backup_size) {
100 Total_Backup_Size = backup_size;
101}
102
Ethan Yonker87af5632014-02-10 11:56:35 -0600103void twrpTar::setpassword(string pass) {
104 password = pass;
105}
106
bigbiff7abc5fe2015-01-17 16:53:12 -0500107void twrpTar::Signal_Kill(int signum) {
108 _exit(255);
109}
110
bigbiffce8f83c2015-12-12 18:30:21 -0500111void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
112 current_archive_type = archive_type;
113}
114
115int twrpTar::createTarFork(pid_t *tar_fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000116 int status = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500117 pid_t rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500118 int progress_pipe[2], ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500119 char cmd[512];
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500120
121 file_count = 0;
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600122 if (backup_exclusions == NULL) {
123 LOGINFO("backup_exclusions is NULL\n");
124 return -1;
125 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500126
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600127#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500128 if (part_settings->adbbackup) {
129 std::string Backup_FileName(tarfn);
130 if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
131 return -1;
132 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600133#endif
bigbiffce8f83c2015-12-12 18:30:21 -0500134
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500135 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500136 LOGINFO("Error creating progress tracking pipe\n");
137 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500138 return -1;
139 }
bigbiffce8f83c2015-12-12 18:30:21 -0500140 if ((*tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000141 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500142 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500143 close(progress_pipe[0]);
144 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500145 return -1;
146 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500147
bigbiffce8f83c2015-12-12 18:30:21 -0500148 if (*tar_fork_pid == 0) {
bigbiff7abc5fe2015-01-17 16:53:12 -0500149 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500150 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500151 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500152 close(progress_pipe[0]);
153 progress_pipe_fd = progress_pipe[1];
154
Dees_Troy83bd4832013-05-04 12:39:56 +0000155 if (use_encryption || userdata_encryption) {
156 LOGINFO("Using encryption\n");
157 DIR* d;
158 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200159 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
160 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000161 int item_len, ret, thread_error = 0;
162 std::vector<TarListStruct> RegularList;
163 std::vector<TarListStruct> EncryptList;
164 string FileName;
165 struct TarListStruct TarItem;
166 twrpTar reg, enc[9];
167 struct stat st;
168 pthread_t enc_thread[9];
169 pthread_attr_t tattr;
170 void *thread_return;
171
172 core_count = sysconf(_SC_NPROCESSORS_CONF);
173 if (core_count > 8)
174 core_count = 8;
that2252d242015-04-03 22:33:04 +0200175 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000176 Archive_Current_Size = 0;
177
178 d = opendir(tardir.c_str());
179 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500180 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500181 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000182 _exit(-1);
183 }
184 // Figure out the size of all data to be encrypted and create a list of unencrypted files
185 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500186 FileName = tardir + "/" + de->d_name;
187
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600188 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000189 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500190 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000191 item_len = strlen(de->d_name);
192 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 -0500193 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
194 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500195 LOGINFO("Error in Generate_TarList with regular list!\n");
196 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000197 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500198 close(progress_pipe_fd);
199 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000200 _exit(-1);
201 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500202 file_count = (unsigned long long)(ret);
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600203 regular_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000204 } else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600205 encrypt_size += backup_exclusions->Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000206 }
207 } else if (de->d_type == DT_REG) {
208 stat(FileName.c_str(), &st);
209 encrypt_size += (unsigned long long)(st.st_size);
210 }
211 }
212 closedir(d);
213
214 target_size = encrypt_size / core_count;
215 target_size++;
216 LOGINFO(" Unencrypted size: %llu\n", regular_size);
217 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
218 LOGINFO(" Target size : %llu\n", target_size);
219 if (!userdata_encryption) {
220 enc_thread_id = 0;
221 start_thread_id = 0;
222 core_count--;
223 }
224 Archive_Current_Size = 0;
225
226 d = opendir(tardir.c_str());
227 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500228 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500229 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000230 _exit(-1);
231 }
232 // Divide up the encrypted file list for threading
233 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500234 FileName = tardir + "/" + de->d_name;
235
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600236 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000237 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500238 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000239 item_len = strlen(de->d_name);
240 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
241 // Do nothing, we added these to RegularList earlier
242 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500243 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500244 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
245 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500246 LOGINFO("Error in Generate_TarList with encrypted list!\n");
247 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000248 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500249 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000250 _exit(-1);
251 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500252 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000253 }
254 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
255 stat(FileName.c_str(), &st);
256 if (de->d_type == DT_REG)
257 Archive_Current_Size += (unsigned long long)(st.st_size);
258 TarItem.fn = FileName;
259 TarItem.thread_id = enc_thread_id;
260 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500261 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000262 }
263 }
264 closedir(d);
265 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500266 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 -0500267 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500268 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500269 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000270 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500271 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500272 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500273 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000274 }
275
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500276 // Send file count to parent
277 write(progress_pipe_fd, &file_count, sizeof(file_count));
278 // Send backup size to parent
279 total_size = regular_size + encrypt_size;
280 write(progress_pipe_fd, &total_size, sizeof(total_size));
281
Dees_Troy83bd4832013-05-04 12:39:56 +0000282 if (userdata_encryption) {
283 // Create a backup of unencrypted data
284 reg.setfn(tarfn);
285 reg.ItemList = &RegularList;
286 reg.thread_id = 0;
287 reg.use_encryption = 0;
288 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000289 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500290 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500291 reg.part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000292 LOGINFO("Creating unencrypted backup...\n");
293 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500294 LOGINFO("Error creating unencrypted backup.\n");
295 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500296 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000297 _exit(-1);
298 }
299 }
300
301 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500302 LOGINFO("Unable to pthread_attr_init\n");
303 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500304 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000305 _exit(-1);
306 }
307 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500308 LOGINFO("Error setting pthread_attr_setdetachstate\n");
309 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500310 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000311 _exit(-1);
312 }
313 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500314 LOGINFO("Error setting pthread_attr_setscope\n");
315 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500316 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000317 _exit(-1);
318 }
319 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
320 LOGERR("Error setting pthread_attr_setstacksize\n");
321 _exit(-1);
322 }*/
323
324 // Create threads for the divided up encryption lists
325 for (i = start_thread_id; i <= core_count; i++) {
326 enc[i].setdir(tardir);
327 enc[i].setfn(tarfn);
328 enc[i].ItemList = &EncryptList;
329 enc[i].thread_id = i;
330 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500331 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000332 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000333 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500334 enc[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500335 enc[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000336 LOGINFO("Start encryption thread %i\n", i);
337 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
338 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500339 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 +0000340 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500341 LOGINFO("Error creating encrypted backup %i.\n", i);
342 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500343 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000344 _exit(-1);
345 } else {
346 enc[i].thread_id = i + 1;
347 }
348 }
349 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
350 }
351 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500352 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000353 }
354 for (i = start_thread_id; i <= core_count; i++) {
355 if (enc[i].thread_id == i) {
356 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500357 LOGINFO("Error joining thread %i\n", i);
358 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500359 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000360 _exit(-1);
361 } else {
362 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200363 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000364 if (ret != 0) {
365 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500366 LOGINFO("Thread %i returned an error %i.\n", i, ret);
367 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500368 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000369 _exit(-1);
370 }
371 }
372 } else {
373 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
374 }
375 }
376 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500377 LOGINFO("Error returned by one or more threads.\n");
378 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500379 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000380 _exit(-1);
381 }
382 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500383 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000384 _exit(0);
385 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500386 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000387 std::vector<TarListStruct> FileList;
388 unsigned thread_id = 0;
389 unsigned long long target_size = 0;
390 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500391 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000392
393 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500394 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
395 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500396 LOGINFO("Error in Generate_TarList!\n");
397 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500398 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000399 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000400 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500401 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000402 // Create a backup
403 reg.setfn(tarfn);
404 reg.ItemList = &FileList;
405 reg.thread_id = 0;
406 reg.use_encryption = 0;
407 reg.use_compression = use_compression;
408 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500409 reg.progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500410 reg.part_settings = part_settings;
411 if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500412 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000413 reg.split_archives = 1;
414 } else {
415 reg.split_archives = 0;
416 }
417 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500418 write(progress_pipe_fd, &file_count, sizeof(file_count));
419 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000420 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500421 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500422 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000423 _exit(-1);
424 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500425 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000426 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000427 }
428 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500429 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600430 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500431 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500432
433 // Parent closes output side
434 close(progress_pipe[1]);
435
436 // Read progress data from children
437 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
438 if (first_data == 0) {
439 // First incoming data is the file count
440 file_count = fs;
441 if (file_count == 0) file_count = 1; // prevent division by 0 below
442 first_data = 1;
443 } else if (first_data == 1) {
444 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500445 first_data = 2;
bigbiffce8f83c2015-12-12 18:30:21 -0500446 part_settings->progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500447 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600448 if (fs > 0) {
449 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500450 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600451 } else { // fs == 0 increments the file counter
452 files_backup++;
bigbiffce8f83c2015-12-12 18:30:21 -0500453 part_settings->progress->UpdateSizeCount(size_backup, files_backup);
Ethan Yonker472f5062016-02-25 13:47:30 -0600454 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500455 }
456 }
457 close(progress_pipe[0]);
458#ifndef BUILD_TWRPTAR_MAIN
459 DataManager::SetValue("tw_file_progress", "");
460 DataManager::SetValue("tw_size_progress", "");
bigbiffce8f83c2015-12-12 18:30:21 -0500461 part_settings->progress->DisplayFileCount(false);
462 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500463
bigbiffce8f83c2015-12-12 18:30:21 -0500464 if (!part_settings->adbbackup) {
James Christopher Adduono90594992016-10-25 00:51:27 -0400465 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
bigbiffce8f83c2015-12-12 18:30:21 -0500466 backup_info.SetValue("backup_size", size_backup);
467 if (use_compression && use_encryption)
468 backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED);
469 else if (use_encryption)
470 backup_info.SetValue("backup_type", ENCRYPTED);
471 else if (use_compression)
472 backup_info.SetValue("backup_type", COMPRESSED);
473 else
474 backup_info.SetValue("backup_type", UNCOMPRESSED);
475 backup_info.SetValue("file_count", files_backup);
476 backup_info.SaveValues();
477 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500478#endif //ndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500479 if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500480 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500481 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500482 return 0;
483}
484
bigbiffce8f83c2015-12-12 18:30:21 -0500485int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000486 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500487 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500488 int progress_pipe[2], ret;
489
490 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500491 LOGINFO("Error creating progress tracking pipe\n");
492 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500493 return -1;
494 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000495
bigbiff7abc5fe2015-01-17 16:53:12 -0500496 tar_fork_pid = fork();
497 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000498 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500499 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000500 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500501 close(progress_pipe[0]);
502 progress_pipe_fd = progress_pipe[1];
bigbiffce8f83c2015-12-12 18:30:21 -0500503 if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000504 LOGINFO("Single archive\n");
505 if (extract() != 0)
506 _exit(-1);
bigbiffce8f83c2015-12-12 18:30:21 -0500507 else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000508 _exit(0);
bigbiffce8f83c2015-12-12 18:30:21 -0500509 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000510 } else {
511 LOGINFO("Multiple archives\n");
512 string temp;
513 char actual_filename[255];
514 twrpTar tars[9];
515 pthread_t tar_thread[9];
516 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500517 unsigned thread_count = 0, i, start_thread_id = 1;
518 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000519 void *thread_return;
520
521 basefn = tarfn;
522 temp = basefn + "%i%02i";
523 tarfn += "000";
524 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500525 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
526 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500527 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000528 _exit(-1);
529 }
530 if (TWFunc::Get_File_Type(tarfn) != 2) {
531 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
532 tars[0].basefn = basefn;
533 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500534 tars[0].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500535 tars[0].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000536 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500537 LOGINFO("Error extracting split archive.\n");
538 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500539 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000540 _exit(-1);
541 }
542 } else {
543 start_thread_id = 0;
544 }
545 // Start threading encrypted restores
546 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500547 LOGINFO("Unable to pthread_attr_init\n");
548 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500549 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 _exit(-1);
551 }
552 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500553 LOGINFO("Error setting pthread_attr_setdetachstate\n");
554 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500555 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000556 _exit(-1);
557 }
558 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500559 LOGINFO("Error setting pthread_attr_setscope\n");
560 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500561 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000562 _exit(-1);
563 }
564 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
565 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500566 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000567 _exit(-1);
568 }*/
569 for (i = start_thread_id; i < 9; i++) {
570 sprintf(actual_filename, temp.c_str(), i, 0);
571 if (TWFunc::Path_Exists(actual_filename)) {
572 thread_count++;
573 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500574 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000575 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500576 tars[i].progress_pipe_fd = progress_pipe_fd;
bigbiffce8f83c2015-12-12 18:30:21 -0500577 tars[i].part_settings = part_settings;
Dees_Troy83bd4832013-05-04 12:39:56 +0000578 LOGINFO("Creating extract thread ID %i\n", i);
579 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
580 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500581 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 +0000582 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500583 LOGINFO("Error extracting backup in thread %i.\n", i);
584 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500585 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000586 _exit(-1);
587 } else {
588 tars[i].thread_id = i + 1;
589 }
590 }
591 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
592 } else {
593 break;
594 }
595 }
596 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
597 if (tars[i].thread_id == i) {
598 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500599 LOGINFO("Error joining thread %i\n", i);
600 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500601 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000602 _exit(-1);
603 } else {
604 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200605 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000606 if (ret != 0) {
607 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500608 LOGINFO("Thread %i returned an error %i.\n", i, ret);
609 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500610 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000611 _exit(-1);
612 }
613 }
614 } else {
615 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
616 }
617 }
618 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500619 LOGINFO("Error returned by one or more threads.\n");
620 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500621 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000622 _exit(-1);
623 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500624 LOGINFO("Finished encrypted restore.\n");
625 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000626 _exit(0);
627 }
628 }
629 else // parent process
630 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600631 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500632
633 // Parent closes output side
634 close(progress_pipe[1]);
635
636 // Read progress data from children
637 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
638 size_backup += fs;
bigbiffce8f83c2015-12-12 18:30:21 -0500639 part_settings->progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500640 }
641 close(progress_pipe[0]);
bigbiffce8f83c2015-12-12 18:30:21 -0500642 part_settings->progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500643
bigbiff7abc5fe2015-01-17 16:53:12 -0500644 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000645 return -1;
646 }
647 }
648 else // fork has failed
649 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500650 close(progress_pipe[0]);
651 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000652 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500653 return -1;
654 }
655 return 0;
656}
657
Dees_Troy83bd4832013-05-04 12:39:56 +0000658int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
659 DIR* d;
660 struct dirent* de;
661 struct stat st;
662 string FileName;
663 struct TarListStruct TarItem;
664 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500665 int ret, file_count;
666 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000667
Dees_Troy83bd4832013-05-04 12:39:56 +0000668 d = opendir(Path.c_str());
669 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500670 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000671 closedir(d);
672 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500673 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000674 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500675 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500676
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600677 if (de->d_type == DT_BLK || de->d_type == DT_CHR || backup_exclusions->check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000678 continue;
679 TarItem.fn = FileName;
680 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500681 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000682 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500683 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
684 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500685 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500686 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000687 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
688 stat(FileName.c_str(), &st);
689 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500690 if (de->d_type == DT_REG) {
691 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000692 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500693 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000694 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
695 *thread_id = *thread_id + 1;
696 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500697 }
698 }
699 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000700 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500701 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500702}
703
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500704int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000705 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000706 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500707 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500708 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500709 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
710 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500711 return -1;
712 }
713 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500714 LOGINFO("Unable to close tar file\n");
715 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500716 return -1;
717 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600718#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -0500719 if (part_settings->adbbackup) {
720 if (!twadbbu::Write_TWEOF())
721 return -1;
722 }
Ethan Yonker3fdcda42016-11-30 12:29:37 -0600723#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500724 return 0;
725}
726
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500727int twrpTar::extract() {
bigbiffce8f83c2015-12-12 18:30:21 -0500728 if (!part_settings->adbbackup) {
729 LOGINFO("Setting archive type\n");
730 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
731 }
732 else {
733 if (part_settings->adb_compression == 1)
734 current_archive_type = COMPRESSED;
735 else
736 current_archive_type = UNCOMPRESSED;
737 }
n0d33b511632013-03-06 21:14:15 +0200738
bigbiffce8f83c2015-12-12 18:30:21 -0500739 if (current_archive_type == COMPRESSED) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500740 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000741 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000742 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500743 return ret;
bigbiffce8f83c2015-12-12 18:30:21 -0500744 } else if (current_archive_type == ENCRYPTED) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600745 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000746 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500747 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000748 return -1;
749 }
750 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500751 LOGINFO("Decrypted file is not in tar format.\n");
752 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000753 return -1;
754 }
755 if (ret == 3) {
756 LOGINFO("Extracting encrypted and compressed tar.\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500757 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000758 } else
759 LOGINFO("Extracting encrypted tar.\n");
760 return extractTar();
761 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000762 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500763 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500764 }
765}
766
Dees Troye0a433a2013-12-02 04:10:37 +0000767int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000768 struct stat st;
769 char buf[PATH_MAX];
770 int list_size = TarList->size(), i = 0, archive_count = 0;
771 string temp;
772 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000773 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500774 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000775
Dees Troye0a433a2013-12-02 04:10:37 +0000776 if (split_archives) {
777 basefn = tarfn;
778 temp = basefn + "%i%02i";
779 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
780 tarfn = actual_filename;
781 include_root_dir = true;
782 } else {
783 include_root_dir = false;
784 }
bigbiffce8f83c2015-12-12 18:30:21 -0500785
786 if (part_settings->adbbackup)
787 LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str());
788 else
789 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
790
Dees_Troy83bd4832013-05-04 12:39:56 +0000791 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500792 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
793 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000794 return -2;
795 }
796 Archive_Current_Size = 0;
797
798 while (i < list_size) {
799 if (TarList->at(i).thread_id == thread_id) {
800 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400801 lstat(buf, &st);
802 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500803 fs = (unsigned long long)(st.st_size);
804 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000805 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500806 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
807 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000808 return -3;
809 }
810 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500811 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000812 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500813 LOGINFO("Too many archives for thread %i\n", thread_id);
814 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000815 return -4;
816 }
817 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
818 tarfn = actual_filename;
819 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500820 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
821 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000822 return -2;
823 }
824 Archive_Current_Size = 0;
825 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500826 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600827 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500828 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000829 }
Dees Troye0a433a2013-12-02 04:10:37 +0000830 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
831 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500832 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
833 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000834 return -1;
835 }
836 }
837 i++;
838 }
839 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500840 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
841 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000842 return -3;
843 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600844 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000845 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500846}
847
Dees_Troy83bd4832013-05-04 12:39:56 +0000848void* twrpTar::createList(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000849 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600850 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000851 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
852 return (void*)-2;
853 }
854 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
855 return (void*)0;
856}
857
858void* twrpTar::extractMulti(void *cookie) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000859 twrpTar* threadTar = (twrpTar*) cookie;
860 int archive_count = 0;
861 string temp = threadTar->basefn + "%i%02i";
862 char actual_filename[255];
863 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
864 while (TWFunc::Path_Exists(actual_filename)) {
865 threadTar->tarfn = actual_filename;
866 if (threadTar->extract() != 0) {
867 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
868 return (void*)-2;
869 }
870 archive_count++;
871 if (archive_count > 99)
872 break;
873 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
874 }
875 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
876 return (void*)0;
877}
878
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500879int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
880 char* charTarFile = (char*) fn.c_str();
881
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600882 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500883 return -1;
884 removeEOT(charTarFile);
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600885 if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500886 return -1;
887 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500888 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500889 if (tar_append_file(t, file, file) == -1)
890 return -1;
891 }
892 if (tar_append_eof(t) == -1)
893 return -1;
894 if (tar_close(t) == -1)
895 return -1;
896 return 0;
897}
898
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500899int twrpTar::createTar() {
900 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000901 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500902
Dees_Troy83bd4832013-05-04 12:39:56 +0000903 if (use_encryption && use_compression) {
904 // Compressed and encrypted
bigbiffce8f83c2015-12-12 18:30:21 -0500905 current_archive_type = COMPRESSED_ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +0000906 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000907 int i, pipes[4];
908
909 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500910 LOGINFO("Error creating first pipe\n");
911 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500912 return -1;
913 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000914 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500915 LOGINFO("Error creating second pipe\n");
916 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500917 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000918 }
bigbiffce8f83c2015-12-12 18:30:21 -0500919 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
Dees Troy9d723272014-04-07 17:13:10 +0000920 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500921 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000922 for (i = 0; i < 4; i++)
923 close(pipes[i]); // close all
924 return -1;
925 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000926 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400927
Dees_Troy83bd4832013-05-04 12:39:56 +0000928 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500929 LOGINFO("pigz fork() failed\n");
930 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000931 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000932 for (i = 0; i < 4; i++)
933 close(pipes[i]); // close all
934 return -1;
935 } else if (pigz_pid == 0) {
936 // pigz Child
937 close(pipes[1]);
938 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500939 int stdinfd = fileno(stdin);
940 int stdoutfd = fileno(stdout);
941 close(stdinfd);
942 dup2(pipes[0], stdinfd);
943 close(stdoutfd);
944 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000945 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500946 LOGINFO("execlp pigz ERROR!\n");
947 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000948 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000949 close(pipes[0]);
950 close(pipes[3]);
951 _exit(-1);
952 }
953 } else {
954 // Parent
955 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400956
Dees_Troy83bd4832013-05-04 12:39:56 +0000957 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500958 LOGINFO("openaes fork() failed\n");
959 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000960 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000961 for (i = 0; i < 4; i++)
962 close(pipes[i]); // close all
963 return -1;
964 } else if (oaes_pid == 0) {
965 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000966 close(pipes[0]);
967 close(pipes[1]);
968 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -0500969 int stdinfd = fileno(stdin);
970 int stdoutfd = fileno(stdout);
971 close(stdinfd);
972 dup2(pipes[2], stdinfd);
973 close(stdoutfd);
974 dup2(output_fd, stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -0600975 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500976 LOGINFO("execlp openaes ERROR!\n");
977 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000978 close(pipes[2]);
979 close(output_fd);
980 _exit(-1);
981 }
982 } else {
983 // Parent
984 close(pipes[0]);
985 close(pipes[2]);
986 close(pipes[3]);
987 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600988 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -0500989 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker79f88bd2016-12-09 14:52:12 -0600990 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000991 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500992 LOGINFO("tar_fdopen failed\n");
993 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000994 return -1;
995 }
996 return 0;
997 }
998 }
999 } else if (use_compression) {
1000 // Compressed
bigbiffce8f83c2015-12-12 18:30:21 -05001001 current_archive_type = COMPRESSED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001002 LOGINFO("Using compression...\n");
1003 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001004 if (part_settings->adbbackup) {
1005 LOGINFO("opening TW_ADB_BACKUP compressed stream\n");
1006 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
1007 }
1008 else {
1009 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1010 }
Dees Troy9d723272014-04-07 17:13:10 +00001011 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001012 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001013 close(pigzfd[0]);
1014 return -1;
1015 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001016
1017 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001018 LOGINFO("Error creating pipe\n");
1019 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001020 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001021 return -1;
1022 }
1023 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001024
Dees_Troy83bd4832013-05-04 12:39:56 +00001025 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001026 LOGINFO("fork() failed\n");
1027 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001028 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001029 close(pigzfd[0]);
1030 close(pigzfd[1]);
1031 return -1;
1032 } else if (pigz_pid == 0) {
1033 // Child
1034 close(pigzfd[1]); // close unused output pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001035 dup2(pigzfd[0], fileno(stdin)); // remap stdin
1036 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Dees_Troy83bd4832013-05-04 12:39:56 +00001037 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001038 LOGINFO("execlp pigz ERROR!\n");
1039 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001040 close(output_fd);
1041 close(pigzfd[0]);
1042 _exit(-1);
1043 }
1044 } else {
1045 // Parent
1046 close(pigzfd[0]); // close parent input
1047 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001048 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001049 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001050 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001051 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001052 LOGINFO("tar_fdopen failed\n");
1053 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 return -1;
1055 }
1056 }
1057 } else if (use_encryption) {
1058 // Encrypted
bigbiffce8f83c2015-12-12 18:30:21 -05001059 current_archive_type = ENCRYPTED;
Dees_Troy83bd4832013-05-04 12:39:56 +00001060 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001061 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001062 output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
Dees Troy9d723272014-04-07 17:13:10 +00001063 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001064 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001065 return -1;
1066 }
1067 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001068 LOGINFO("Error creating pipe\n");
1069 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001070 close(output_fd);
1071 return -1;
1072 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001073 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001074
Dees_Troy83bd4832013-05-04 12:39:56 +00001075 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001076 LOGINFO("fork() failed\n");
1077 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001078 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001079 close(oaesfd[0]);
1080 close(oaesfd[1]);
1081 return -1;
1082 } else if (oaes_pid == 0) {
1083 // Child
1084 close(oaesfd[1]); // close unused
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001085 dup2(oaesfd[0], fileno(stdin)); // remap stdin
1086 dup2(output_fd, fileno(stdout)); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001087 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001088 LOGINFO("execlp openaes ERROR!\n");
1089 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001090 close(output_fd);
1091 close(oaesfd[0]);
1092 _exit(-1);
1093 }
1094 } else {
1095 // Parent
1096 close(oaesfd[0]); // close parent input
1097 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001098 init_libtar_no_buffer(progress_pipe_fd);
Ethan Yonkerf1179622016-08-25 15:32:21 -05001099 tar_type.writefunc = write_tar_no_buffer;
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001100 if(tar_fdopen(&t, fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001101 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001102 LOGINFO("tar_fdopen failed\n");
1103 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001104 return -1;
1105 }
1106 return 0;
1107 }
1108 } else {
1109 // Not compressed or encrypted
Ethan Yonker472f5062016-02-25 13:47:30 -06001110 init_libtar_buffer(0, progress_pipe_fd);
bigbiffce8f83c2015-12-12 18:30:21 -05001111 if (part_settings->adbbackup) {
1112 LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n");
Ethan Yonkerf1179622016-08-25 15:32:21 -05001113 tar_type.writefunc = write_tar_no_buffer;
bigbiffce8f83c2015-12-12 18:30:21 -05001114 output_fd = open(TW_ADB_BACKUP, O_WRONLY);
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001115 if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001116 close(output_fd);
1117 LOGERR("tar_fdopen failed\n");
1118 return -1;
1119 }
1120 }
1121 else {
Ethan Yonkerf1179622016-08-25 15:32:21 -05001122 tar_type.writefunc = write_tar;
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001123 if (tar_open(&t, charTarFile, &tar_type, O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) == -1) {
bigbiffce8f83c2015-12-12 18:30:21 -05001124 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1125 gui_err("backup_error=Error creating backup.");
1126 return -1;
1127 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001128 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001129 }
1130 return 0;
1131}
1132
Dees_Troy83bd4832013-05-04 12:39:56 +00001133int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001134 char* charRootDir = (char*) tardir.c_str();
1135 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001136 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001137
bigbiffce8f83c2015-12-12 18:30:21 -05001138 if (current_archive_type == COMPRESSED_ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001139 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001140 int i, pipes[4];
bigbiffce8f83c2015-12-12 18:30:21 -05001141 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001142 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001143 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001144 return -1;
1145 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001146
1147 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001148 LOGINFO("Error creating first pipe\n");
1149 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001150 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001151 return -1;
1152 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001153 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001154 LOGINFO("Error creating second pipe\n");
1155 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001156 close(pipes[0]);
1157 close(pipes[1]);
1158 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001159 return -1;
1160 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001161 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001162
Dees_Troy83bd4832013-05-04 12:39:56 +00001163 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001164 LOGINFO("pigz fork() failed\n");
1165 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001166 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001167 for (i = 0; i < 4; i++)
1168 close(pipes[i]); // close all
1169 return -1;
1170 } else if (oaes_pid == 0) {
1171 // openaes Child
1172 close(pipes[0]); // Close pipes that are not used by this child
1173 close(pipes[2]);
1174 close(pipes[3]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001175 int stdinfd = fileno(stdin);
1176 int stdoutfd = fileno(stdout);
1177 close(stdinfd);
1178 dup2(input_fd, stdinfd);
1179 close(stdoutfd);
1180 dup2(pipes[1], stdoutfd);
Ethan Yonker87af5632014-02-10 11:56:35 -06001181 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001182 LOGINFO("execlp openaes ERROR!\n");
1183 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001184 close(input_fd);
1185 close(pipes[1]);
1186 _exit(-1);
1187 }
1188 } else {
1189 // Parent
1190 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001191
Dees_Troy83bd4832013-05-04 12:39:56 +00001192 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001193 LOGINFO("openaes fork() failed\n");
1194 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001195 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001196 for (i = 0; i < 4; i++)
1197 close(pipes[i]); // close all
1198 return -1;
1199 } else if (pigz_pid == 0) {
1200 // pigz Child
1201 close(pipes[1]); // Close pipes not used by this child
1202 close(pipes[2]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001203 int stdinfd = fileno(stdin);
1204 int stdoutfd = fileno(stdout);
1205 close(stdinfd);
1206 dup2(pipes[0], stdinfd);
1207 close(stdoutfd);
1208 dup2(pipes[3], stdoutfd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001209 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001210 LOGINFO("execlp pigz ERROR!\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(pipes[0]);
1214 close(pipes[3]);
1215 _exit(-1);
1216 }
1217 } else {
1218 // Parent
1219 close(pipes[0]); // Close pipes not used by parent
1220 close(pipes[1]);
1221 close(pipes[3]);
1222 fd = pipes[2];
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001223 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001224 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001225 LOGINFO("tar_fdopen failed\n");
1226 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001227 return -1;
1228 }
1229 }
1230 }
bigbiffce8f83c2015-12-12 18:30:21 -05001231 } else if (current_archive_type == ENCRYPTED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001232 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001233 int oaesfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001234 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
Dees Troy9d723272014-04-07 17:13:10 +00001235 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001236 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001237 return -1;
1238 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001239
Dees Troy9d723272014-04-07 17:13:10 +00001240 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001241 LOGINFO("Error creating pipe\n");
1242 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001243 close(input_fd);
1244 return -1;
1245 }
1246
Dees_Troy83bd4832013-05-04 12:39:56 +00001247 oaes_pid = fork();
1248 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001249 LOGINFO("fork() failed\n");
1250 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001251 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001252 close(oaesfd[0]);
1253 close(oaesfd[1]);
1254 return -1;
1255 } else if (oaes_pid == 0) {
1256 // Child
1257 close(oaesfd[0]); // Close unused pipe
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001258 int stdinfd = fileno(stdin);
1259 close(stdinfd); // close stdin
1260 dup2(oaesfd[1], fileno(stdout)); // remap stdout
1261 dup2(input_fd, stdinfd); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001262 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001263 LOGINFO("execlp openaes ERROR!\n");
1264 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001265 close(input_fd);
1266 close(oaesfd[1]);
1267 _exit(-1);
1268 }
1269 } else {
1270 // Parent
1271 close(oaesfd[1]); // close parent output
1272 fd = oaesfd[0]; // copy parent input
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001273 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001274 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001275 LOGINFO("tar_fdopen failed\n");
1276 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001277 return -1;
1278 }
1279 }
bigbiffce8f83c2015-12-12 18:30:21 -05001280 } else if (current_archive_type == COMPRESSED) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001281 int pigzfd[2];
bigbiffce8f83c2015-12-12 18:30:21 -05001282
1283 LOGINFO("Opening as a gzip...\n");
1284 if (part_settings->adbbackup) {
1285 LOGINFO("opening TW_ADB_RESTORE compressed stream\n");
1286 input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE);
1287 }
1288 else
1289 input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1290
Dees Troy9d723272014-04-07 17:13:10 +00001291 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001292 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001293 return -1;
1294 }
bigbiffce8f83c2015-12-12 18:30:21 -05001295
Dees Troy9d723272014-04-07 17:13:10 +00001296 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001297 LOGINFO("Error creating pipe\n");
1298 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001299 close(input_fd);
1300 return -1;
1301 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001302
1303 pigz_pid = fork();
1304 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001305 LOGINFO("fork() failed\n");
1306 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001307 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001308 close(pigzfd[0]);
1309 close(pigzfd[1]);
1310 return -1;
1311 } else if (pigz_pid == 0) {
1312 // Child
1313 close(pigzfd[0]);
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001314 dup2(pigzfd[1], fileno(stdout)); // remap stdout
1315 dup2(input_fd, fileno(stdin)); // remap input fd to stdin
Dees_Troy83bd4832013-05-04 12:39:56 +00001316 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1317 close(pigzfd[1]);
1318 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001319 LOGINFO("execlp openaes ERROR!\n");
1320 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001321 _exit(-1);
1322 }
1323 } else {
1324 // Parent
1325 close(pigzfd[1]); // close parent output
1326 fd = pigzfd[0]; // copy parent input
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001327 if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001328 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001329 LOGINFO("tar_fdopen failed\n");
1330 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001331 return -1;
1332 }
1333 }
bigbiffce8f83c2015-12-12 18:30:21 -05001334 } else {
1335 if (part_settings->adbbackup) {
1336 LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n");
1337 input_fd = open(TW_ADB_RESTORE, O_RDONLY);
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001338 if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001339 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1340 gui_err("restore_error=Error during restore process.");
1341 return -1;
1342 }
1343 }
1344 else {
Ethan Yonker79f88bd2016-12-09 14:52:12 -06001345 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TWTAR_FLAGS) != 0) {
bigbiffce8f83c2015-12-12 18:30:21 -05001346 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1347 gui_err("restore_error=Error during restore process.");
1348 return -1;
1349 }
1350 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001351 }
1352 return 0;
1353}
1354
1355string twrpTar::Strip_Root_Dir(string Path) {
1356 string temp;
1357 size_t slash;
1358
1359 if (Path.substr(0, 1) == "/")
1360 temp = Path.substr(1, Path.size() - 1);
1361 else
1362 temp = Path;
1363 slash = temp.find("/");
1364 if (slash == string::npos)
1365 return temp;
1366 else {
1367 string stripped;
1368
1369 stripped = temp.substr(slash, temp.size() - slash);
1370 return stripped;
1371 }
1372 return temp;
1373}
1374
1375int twrpTar::addFile(string fn, bool include_root) {
1376 char* charTarFile = (char*) fn.c_str();
1377 if (include_root) {
1378 if (tar_append_file(t, charTarFile, NULL) == -1)
1379 return -1;
1380 } else {
1381 string temp = Strip_Root_Dir(fn);
1382 char* charTarPath = (char*) temp.c_str();
1383 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1384 return -1;
1385 }
1386 return 0;
1387}
1388
Dees_Troy83bd4832013-05-04 12:39:56 +00001389int twrpTar::closeTar() {
bigbiffce8f83c2015-12-12 18:30:21 -05001390 LOGINFO("Closing tar\n");
Dees_Troye34c1332013-02-06 19:13:00 +00001391 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001392 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001393 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001394 tar_close(t);
1395 return -1;
1396 }
1397 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001398 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001399 return -1;
1400 }
bigbiffce8f83c2015-12-12 18:30:21 -05001401 if (current_archive_type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001402 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001403 int status;
1404 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1405 return -1;
1406 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1407 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001408 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001409 free_libtar_buffer();
bigbiffce8f83c2015-12-12 18:30:21 -05001410 if (!part_settings->adbbackup) {
1411 if (use_compression && !use_encryption) {
1412 string gzname = tarfn + ".gz";
1413 if (TWFunc::Path_Exists(gzname)) {
1414 rename(gzname.c_str(), tarfn.c_str());
1415 }
Dees Troye0a433a2013-12-02 04:10:37 +00001416 }
bigbiffce8f83c2015-12-12 18:30:21 -05001417 if (TWFunc::Get_File_Size(tarfn) == 0) {
1418 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
1419 return -1;
1420 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001421#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001422 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001423#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001424 }
1425 else {
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001426#ifndef BUILD_TWRPTAR_MAIN
bigbiffce8f83c2015-12-12 18:30:21 -05001427 if (!twadbbu::Write_TWEOF())
1428 return -1;
Ethan Yonker3fdcda42016-11-30 12:29:37 -06001429#endif
bigbiffce8f83c2015-12-12 18:30:21 -05001430 }
Ethan Yonkerea2fcf02016-09-12 16:07:19 -05001431 if (input_fd >= 0)
1432 close(input_fd);
1433 if (output_fd >= 0)
1434 close(output_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001435 return 0;
1436}
1437
1438int twrpTar::removeEOT(string tarFile) {
1439 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001440 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001441 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001442 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001443 tar_skip_regfile(t);
1444 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001445 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001446 if (tar_close(t) == -1)
1447 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001448 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001449 return -1;
1450 return 0;
1451}
1452
n0d33b511632013-03-06 21:14:15 +02001453int twrpTar::entryExists(string entry) {
1454 char* searchstr = (char*)entry.c_str();
1455 int ret;
1456
bigbiffce8f83c2015-12-12 18:30:21 -05001457 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
n0d33b511632013-03-06 21:14:15 +02001458
Dees_Troy83bd4832013-05-04 12:39:56 +00001459 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001460 ret = 0;
1461 else
1462 ret = tar_find(t, searchstr);
1463
Dees_Troy83bd4832013-05-04 12:39:56 +00001464 if (closeTar() != 0)
1465 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001466
1467 return ret;
1468}
1469
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001470unsigned long long twrpTar::get_size() {
bigbiffce8f83c2015-12-12 18:30:21 -05001471 if (TWFunc::Path_Exists(tarfn) && !part_settings->adbbackup) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001472 LOGINFO("Single archive\n");
bigbiffce8f83c2015-12-12 18:30:21 -05001473 return uncompressedSize(tarfn);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001474 } else {
1475 LOGINFO("Multiple archives\n");
1476 string temp;
1477 char actual_filename[255];
bigbiffce8f83c2015-12-12 18:30:21 -05001478 int archive_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001479 unsigned long long total_restore_size = 0;
1480
1481 basefn = tarfn;
1482 temp = basefn + "%i%02i";
1483 tarfn += "000";
1484 thread_id = 0;
1485 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
bigbiffce8f83c2015-12-12 18:30:21 -05001486 if (!part_settings->adbbackup) {
1487 if (!TWFunc::Path_Exists(actual_filename)) {
1488 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1489 return 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001490 }
bigbiffce8f83c2015-12-12 18:30:21 -05001491 for (int i = 0; i < 9; i++) {
1492 archive_count = 0;
1493 sprintf(actual_filename, temp.c_str(), i, archive_count);
1494 while (TWFunc::Path_Exists(actual_filename)) {
1495 total_restore_size += uncompressedSize(actual_filename);
1496 archive_count++;
1497 if (archive_count > 99)
1498 break;
1499 sprintf(actual_filename, temp.c_str(), i, archive_count);
1500 }
1501 }
1502 #ifndef BUILD_TWRPTAR_MAIN
1503 if (!part_settings->adbbackup) {
1504 InfoManager backup_info(tarfn + ".info");
1505 backup_info.SetValue("backup_size", total_restore_size);
1506 backup_info.SetValue("backup_type", current_archive_type);
1507 backup_info.SaveValues();
1508 }
1509 #endif //ndef BUILD_TWRPTAR_MAIN
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001510 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001511 return total_restore_size;
1512 }
1513 return 0;
1514}
1515
bigbiffce8f83c2015-12-12 18:30:21 -05001516unsigned long long twrpTar::uncompressedSize(string filename) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001517 unsigned long long total_size = 0;
1518 string Tar, Command, result;
1519 vector<string> split;
1520
bigbiffce8f83c2015-12-12 18:30:21 -05001521 Set_Archive_Type(TWFunc::Get_File_Type(tarfn));
1522 if (current_archive_type == UNCOMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001523 total_size = TWFunc::Get_File_Size(filename);
bigbiffce8f83c2015-12-12 18:30:21 -05001524 } else if (current_archive_type == COMPRESSED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001525 // Compressed
1526 Command = "pigz -l '" + filename + "'";
1527 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1528 we get the uncompressed size at once. */
1529 TWFunc::Exec_Cmd(Command, result);
1530 if (!result.empty()) {
1531 /* Expected output:
1532 compressed original reduced name
1533 95855838 179403776 -1.3% data.yaffs2.win
1534 ^
1535 split[5]
1536 */
1537 split = TWFunc::split_string(result, ' ', true);
1538 if (split.size() > 4)
1539 total_size = atoi(split[5].c_str());
1540 }
bigbiffce8f83c2015-12-12 18:30:21 -05001541 } else if (current_archive_type == COMPRESSED_ENCRYPTED) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001542 // File is encrypted and may be compressed
1543 int ret = TWFunc::Try_Decrypting_File(filename, password);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001544 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001545 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001546 total_size = TWFunc::Get_File_Size(filename);
1547 } else if (ret == 1) {
1548 LOGERR("Decrypted file is not in tar format.\n");
1549 total_size = TWFunc::Get_File_Size(filename);
1550 } else if (ret == 3) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001551 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1552 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1553 we get the uncompressed size at once. */
1554 TWFunc::Exec_Cmd(Command, result);
1555 if (!result.empty()) {
1556 LOGINFO("result was: '%s'\n", result.c_str());
1557 /* Expected output:
1558 compressed original reduced name
1559 95855838 179403776 -1.3% data.yaffs2.win
1560 ^
1561 split[5]
1562 */
1563 split = TWFunc::split_string(result, ' ', true);
1564 if (split.size() > 4)
1565 total_size = atoi(split[5].c_str());
1566 }
1567 } else {
1568 total_size = TWFunc::Get_File_Size(filename);
1569 }
1570 }
1571
1572 return total_size;
1573}
1574
Dees_Troye34c1332013-02-06 19:13:00 +00001575extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1576 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001577}
Ethan Yonker472f5062016-02-25 13:47:30 -06001578
1579extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1580 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1581}