blob: b46f10f60adc1585a10309d683702d0ed51d5982 [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"
Ethan Yonker4b94cfd2014-12-11 10:00:45 -060024 #include "set_metadata.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050025}
26#include <sys/types.h>
27#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050028#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050029#include <string.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050033#include <iostream>
34#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050035#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000036#include <vector>
bigbiff7abc5fe2015-01-17 16:53:12 -050037#include <csignal>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050038#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040039#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050040#include <sys/mman.h>
41#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000042#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050043#include "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050044#include "twrp-functions.hpp"
Ethan Yonker472f5062016-02-25 13:47:30 -060045#include "gui/gui.hpp"
46#include "progresstracking.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050047#ifndef BUILD_TWRPTAR_MAIN
48#include "data.hpp"
49#include "infomanager.hpp"
Ethan Yonker960f0302014-12-21 21:54:00 -060050extern "C" {
51 #include "set_metadata.h"
52}
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050053#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050054
55using namespace std;
56
Dees_Troy83bd4832013-05-04 12:39:56 +000057twrpTar::twrpTar(void) {
58 use_encryption = 0;
59 userdata_encryption = 0;
60 use_compression = 0;
61 split_archives = 0;
62 has_data_media = 0;
63 pigz_pid = 0;
64 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000065 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060066 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000067 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000068}
69
70twrpTar::~twrpTar(void) {
71 // Do nothing
72}
73
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050074void twrpTar::setfn(string fn) {
75 tarfn = fn;
76}
77
78void twrpTar::setdir(string dir) {
79 tardir = dir;
80}
81
Dees Troye0a433a2013-12-02 04:10:37 +000082void twrpTar::setsize(unsigned long long backup_size) {
83 Total_Backup_Size = backup_size;
84}
85
Ethan Yonker87af5632014-02-10 11:56:35 -060086void twrpTar::setpassword(string pass) {
87 password = pass;
88}
89
bigbiff7abc5fe2015-01-17 16:53:12 -050090void twrpTar::Signal_Kill(int signum) {
91 _exit(255);
92}
93
Ethan Yonker472f5062016-02-25 13:47:30 -060094int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +000095 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -050096 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050097 int progress_pipe[2], ret;
98
99 file_count = 0;
100
101 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500102 LOGINFO("Error creating progress tracking pipe\n");
103 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500104 return -1;
105 }
bigbiff7abc5fe2015-01-17 16:53:12 -0500106 if ((tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000107 LOGINFO("create tar failed to fork.\n");
Ethan Yonker74db1572015-10-28 12:44:49 -0500108 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500109 close(progress_pipe[0]);
110 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500111 return -1;
112 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500113
bigbiff7abc5fe2015-01-17 16:53:12 -0500114 if (tar_fork_pid == 0) {
115 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500116 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500117 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500118 close(progress_pipe[0]);
119 progress_pipe_fd = progress_pipe[1];
120
Dees_Troy83bd4832013-05-04 12:39:56 +0000121 if (use_encryption || userdata_encryption) {
122 LOGINFO("Using encryption\n");
123 DIR* d;
124 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200125 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
126 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000127 int item_len, ret, thread_error = 0;
128 std::vector<TarListStruct> RegularList;
129 std::vector<TarListStruct> EncryptList;
130 string FileName;
131 struct TarListStruct TarItem;
132 twrpTar reg, enc[9];
133 struct stat st;
134 pthread_t enc_thread[9];
135 pthread_attr_t tattr;
136 void *thread_return;
137
138 core_count = sysconf(_SC_NPROCESSORS_CONF);
139 if (core_count > 8)
140 core_count = 8;
that2252d242015-04-03 22:33:04 +0200141 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000142 Archive_Current_Size = 0;
143
144 d = opendir(tardir.c_str());
145 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500146 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500147 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000148 _exit(-1);
149 }
150 // Figure out the size of all data to be encrypted and create a list of unencrypted files
151 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500152 FileName = tardir + "/" + de->d_name;
153
154 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000155 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500156 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000157 item_len = strlen(de->d_name);
158 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 -0500159 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
160 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500161 LOGINFO("Error in Generate_TarList with regular list!\n");
162 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000163 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500164 close(progress_pipe_fd);
165 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000166 _exit(-1);
167 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500168 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500169 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000170 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500171 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000172 }
173 } else if (de->d_type == DT_REG) {
174 stat(FileName.c_str(), &st);
175 encrypt_size += (unsigned long long)(st.st_size);
176 }
177 }
178 closedir(d);
179
180 target_size = encrypt_size / core_count;
181 target_size++;
182 LOGINFO(" Unencrypted size: %llu\n", regular_size);
183 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
184 LOGINFO(" Target size : %llu\n", target_size);
185 if (!userdata_encryption) {
186 enc_thread_id = 0;
187 start_thread_id = 0;
188 core_count--;
189 }
190 Archive_Current_Size = 0;
191
192 d = opendir(tardir.c_str());
193 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500194 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tardir)(strerror(errno)));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500195 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000196 _exit(-1);
197 }
198 // Divide up the encrypted file list for threading
199 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500200 FileName = tardir + "/" + de->d_name;
201
202 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000203 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500204 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000205 item_len = strlen(de->d_name);
206 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
207 // Do nothing, we added these to RegularList earlier
208 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500209 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500210 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
211 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500212 LOGINFO("Error in Generate_TarList with encrypted list!\n");
213 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000214 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500215 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000216 _exit(-1);
217 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500218 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000219 }
220 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
221 stat(FileName.c_str(), &st);
222 if (de->d_type == DT_REG)
223 Archive_Current_Size += (unsigned long long)(st.st_size);
224 TarItem.fn = FileName;
225 TarItem.thread_id = enc_thread_id;
226 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500227 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000228 }
229 }
230 closedir(d);
231 if (enc_thread_id != core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500232 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 -0500233 if (enc_thread_id > core_count) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500234 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500235 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000236 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500237 } else {
Ethan Yonker74db1572015-10-28 12:44:49 -0500238 LOGINFO("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500239 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000240 }
241
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 // Send file count to parent
243 write(progress_pipe_fd, &file_count, sizeof(file_count));
244 // Send backup size to parent
245 total_size = regular_size + encrypt_size;
246 write(progress_pipe_fd, &total_size, sizeof(total_size));
247
Dees_Troy83bd4832013-05-04 12:39:56 +0000248 if (userdata_encryption) {
249 // Create a backup of unencrypted data
250 reg.setfn(tarfn);
251 reg.ItemList = &RegularList;
252 reg.thread_id = 0;
253 reg.use_encryption = 0;
254 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000255 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500256 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000257 LOGINFO("Creating unencrypted backup...\n");
258 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500259 LOGINFO("Error creating unencrypted backup.\n");
260 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500261 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000262 _exit(-1);
263 }
264 }
265
266 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500267 LOGINFO("Unable to pthread_attr_init\n");
268 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);
271 }
272 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500273 LOGINFO("Error setting pthread_attr_setdetachstate\n");
274 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500275 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000276 _exit(-1);
277 }
278 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500279 LOGINFO("Error setting pthread_attr_setscope\n");
280 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500281 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000282 _exit(-1);
283 }
284 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
285 LOGERR("Error setting pthread_attr_setstacksize\n");
286 _exit(-1);
287 }*/
288
289 // Create threads for the divided up encryption lists
290 for (i = start_thread_id; i <= core_count; i++) {
291 enc[i].setdir(tardir);
292 enc[i].setfn(tarfn);
293 enc[i].ItemList = &EncryptList;
294 enc[i].thread_id = i;
295 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500296 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000297 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000298 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500299 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000300 LOGINFO("Start encryption thread %i\n", i);
301 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
302 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500303 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 +0000304 if (createList((void*)&enc[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500305 LOGINFO("Error creating encrypted backup %i.\n", i);
306 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500307 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000308 _exit(-1);
309 } else {
310 enc[i].thread_id = i + 1;
311 }
312 }
313 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
314 }
315 if (pthread_attr_destroy(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500316 LOGINFO("Failed to pthread_attr_destroy\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000317 }
318 for (i = start_thread_id; i <= core_count; i++) {
319 if (enc[i].thread_id == i) {
320 if (pthread_join(enc_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500321 LOGINFO("Error joining thread %i\n", i);
322 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500323 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000324 _exit(-1);
325 } else {
326 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200327 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000328 if (ret != 0) {
329 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500330 LOGINFO("Thread %i returned an error %i.\n", i, ret);
331 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500332 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000333 _exit(-1);
334 }
335 }
336 } else {
337 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
338 }
339 }
340 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500341 LOGINFO("Error returned by one or more threads.\n");
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 }
346 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500347 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000348 _exit(0);
349 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500350 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000351 std::vector<TarListStruct> FileList;
352 unsigned thread_id = 0;
353 unsigned long long target_size = 0;
354 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500355 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000356
357 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500358 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
359 if (ret < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500360 LOGINFO("Error in Generate_TarList!\n");
361 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500362 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000363 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000364 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500365 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000366 // Create a backup
367 reg.setfn(tarfn);
368 reg.ItemList = &FileList;
369 reg.thread_id = 0;
370 reg.use_encryption = 0;
371 reg.use_compression = use_compression;
372 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500373 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000374 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500375 gui_msg("split_backup=Breaking backup file into multiple archives...");
Dees Troye0a433a2013-12-02 04:10:37 +0000376 reg.split_archives = 1;
377 } else {
378 reg.split_archives = 0;
379 }
380 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500381 write(progress_pipe_fd, &file_count, sizeof(file_count));
382 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000383 if (createList((void*)&reg) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500384 gui_err("backup_error=Error creating backup.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500385 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000386 _exit(-1);
387 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500388 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000389 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000390 }
391 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500392 // Parent side
Ethan Yonker472f5062016-02-25 13:47:30 -0600393 unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500394 int first_data = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500395
bigbiff7abc5fe2015-01-17 16:53:12 -0500396 fork_pid = tar_fork_pid;
397
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500398 // Parent closes output side
399 close(progress_pipe[1]);
400
401 // Read progress data from children
402 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
403 if (first_data == 0) {
404 // First incoming data is the file count
405 file_count = fs;
406 if (file_count == 0) file_count = 1; // prevent division by 0 below
407 first_data = 1;
408 } else if (first_data == 1) {
409 // Second incoming data is total size
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500410 first_data = 2;
Ethan Yonker472f5062016-02-25 13:47:30 -0600411 progress->SetSizeCount(fs, file_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500412 } else {
Ethan Yonker472f5062016-02-25 13:47:30 -0600413 if (fs > 0) {
414 size_backup += fs;
415 progress->UpdateSize(size_backup);
416 } else { // fs == 0 increments the file counter
417 files_backup++;
418 progress->UpdateSizeCount(size_backup, files_backup);
419 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500420 }
421 }
422 close(progress_pipe[0]);
423#ifndef BUILD_TWRPTAR_MAIN
424 DataManager::SetValue("tw_file_progress", "");
425 DataManager::SetValue("tw_size_progress", "");
Ethan Yonker472f5062016-02-25 13:47:30 -0600426 progress->DisplayFileCount(false);
427 progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500428
429 InfoManager backup_info(backup_folder + partition_name + ".info");
430 backup_info.SetValue("backup_size", size_backup);
431 if (use_compression && use_encryption)
432 backup_info.SetValue("backup_type", 3);
433 else if (use_encryption)
434 backup_info.SetValue("backup_type", 2);
435 else if (use_compression)
436 backup_info.SetValue("backup_type", 1);
437 else
438 backup_info.SetValue("backup_type", 0);
439 backup_info.SetValue("file_count", files_backup);
440 backup_info.SaveValues();
441#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff7abc5fe2015-01-17 16:53:12 -0500442 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500443 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500444 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500445 return 0;
446}
447
Ethan Yonker472f5062016-02-25 13:47:30 -0600448int twrpTar::extractTarFork(ProgressTracking *progress) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000449 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500450 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500451 int progress_pipe[2], ret;
452
453 if (pipe(progress_pipe) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500454 LOGINFO("Error creating progress tracking pipe\n");
455 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500456 return -1;
457 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000458
bigbiff7abc5fe2015-01-17 16:53:12 -0500459 tar_fork_pid = fork();
460 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000461 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500462 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000463 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500464 close(progress_pipe[0]);
465 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000466 if (TWFunc::Path_Exists(tarfn)) {
467 LOGINFO("Single archive\n");
468 if (extract() != 0)
469 _exit(-1);
470 else
471 _exit(0);
472 } else {
473 LOGINFO("Multiple archives\n");
474 string temp;
475 char actual_filename[255];
476 twrpTar tars[9];
477 pthread_t tar_thread[9];
478 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500479 unsigned thread_count = 0, i, start_thread_id = 1;
480 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000481 void *thread_return;
482
483 basefn = tarfn;
484 temp = basefn + "%i%02i";
485 tarfn += "000";
486 if (!TWFunc::Path_Exists(tarfn)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500487 LOGINFO("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
488 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500489 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000490 _exit(-1);
491 }
492 if (TWFunc::Get_File_Type(tarfn) != 2) {
493 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
494 tars[0].basefn = basefn;
495 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500496 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000497 if (extractMulti((void*)&tars[0]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500498 LOGINFO("Error extracting split archive.\n");
499 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500500 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000501 _exit(-1);
502 }
503 } else {
504 start_thread_id = 0;
505 }
506 // Start threading encrypted restores
507 if (pthread_attr_init(&tattr)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500508 LOGINFO("Unable to pthread_attr_init\n");
509 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500510 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000511 _exit(-1);
512 }
513 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500514 LOGINFO("Error setting pthread_attr_setdetachstate\n");
515 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500516 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000517 _exit(-1);
518 }
519 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500520 LOGINFO("Error setting pthread_attr_setscope\n");
521 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500522 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000523 _exit(-1);
524 }
525 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
526 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500527 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000528 _exit(-1);
529 }*/
530 for (i = start_thread_id; i < 9; i++) {
531 sprintf(actual_filename, temp.c_str(), i, 0);
532 if (TWFunc::Path_Exists(actual_filename)) {
533 thread_count++;
534 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500535 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000536 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500537 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000538 LOGINFO("Creating extract thread ID %i\n", i);
539 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
540 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500541 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 +0000542 if (extractMulti((void*)&tars[i]) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500543 LOGINFO("Error extracting backup in thread %i.\n", i);
544 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500545 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000546 _exit(-1);
547 } else {
548 tars[i].thread_id = i + 1;
549 }
550 }
551 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
552 } else {
553 break;
554 }
555 }
556 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
557 if (tars[i].thread_id == i) {
558 if (pthread_join(tar_thread[i], &thread_return)) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500559 LOGINFO("Error joining thread %i\n", i);
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 } else {
564 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200565 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000566 if (ret != 0) {
567 thread_error = 1;
Ethan Yonker74db1572015-10-28 12:44:49 -0500568 LOGINFO("Thread %i returned an error %i.\n", i, ret);
569 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500570 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000571 _exit(-1);
572 }
573 }
574 } else {
575 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
576 }
577 }
578 if (thread_error) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500579 LOGINFO("Error returned by one or more threads.\n");
580 gui_err("restore_error=Error during restore process.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500581 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000582 _exit(-1);
583 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500584 LOGINFO("Finished encrypted restore.\n");
585 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000586 _exit(0);
587 }
588 }
589 else // parent process
590 {
Ethan Yonker472f5062016-02-25 13:47:30 -0600591 unsigned long long fs, size_backup = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500592
593 // Parent closes output side
594 close(progress_pipe[1]);
595
596 // Read progress data from children
597 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
598 size_backup += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600599 progress->UpdateSize(size_backup);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500600 }
601 close(progress_pipe[0]);
Ethan Yonker472f5062016-02-25 13:47:30 -0600602 progress->UpdateDisplayDetails(true);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500603
bigbiff7abc5fe2015-01-17 16:53:12 -0500604 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000605 return -1;
606 }
607 }
608 else // fork has failed
609 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500610 close(progress_pipe[0]);
611 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000612 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500613 return -1;
614 }
615 return 0;
616}
617
Dees_Troy83bd4832013-05-04 12:39:56 +0000618int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
619 DIR* d;
620 struct dirent* de;
621 struct stat st;
622 string FileName;
623 struct TarListStruct TarItem;
624 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500625 int ret, file_count;
626 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000627
Dees_Troy83bd4832013-05-04 12:39:56 +0000628 d = opendir(Path.c_str());
629 if (d == NULL) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500630 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Path)(strerror(errno)));
Dees_Troy83bd4832013-05-04 12:39:56 +0000631 closedir(d);
632 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500633 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000634 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500635 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500636
Matt Mower50248ab2014-03-31 15:58:40 -0500637 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000638 continue;
639 TarItem.fn = FileName;
640 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500641 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000642 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500643 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
644 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500645 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500646 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000647 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
648 stat(FileName.c_str(), &st);
649 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500650 if (de->d_type == DT_REG) {
651 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000652 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500653 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000654 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
655 *thread_id = *thread_id + 1;
656 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500657 }
658 }
659 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000660 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500661 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500662}
663
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500664int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000665 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000666 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500667 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500668 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500669 LOGINFO("Unable to extract tar archive '%s'\n", tarfn.c_str());
670 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500671 return -1;
672 }
673 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500674 LOGINFO("Unable to close tar file\n");
675 gui_err("restore_error=Error during restore process.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500676 return -1;
677 }
678 return 0;
679}
680
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500681int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000682 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200683
684 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500685 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000686 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000687 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500688 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000689 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600690 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500692 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Dees_Troy83bd4832013-05-04 12:39:56 +0000693 return -1;
694 }
695 if (ret == 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500696 LOGINFO("Decrypted file is not in tar format.\n");
697 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000698 return -1;
699 }
700 if (ret == 3) {
701 LOGINFO("Extracting encrypted and compressed tar.\n");
702 Archive_Current_Type = 3;
703 } else
704 LOGINFO("Extracting encrypted tar.\n");
705 return extractTar();
706 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000707 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500708 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500709 }
710}
711
Dees Troye0a433a2013-12-02 04:10:37 +0000712int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000713 struct stat st;
714 char buf[PATH_MAX];
715 int list_size = TarList->size(), i = 0, archive_count = 0;
716 string temp;
717 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000718 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500719 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000720
Dees Troye0a433a2013-12-02 04:10:37 +0000721 if (split_archives) {
722 basefn = tarfn;
723 temp = basefn + "%i%02i";
724 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
725 tarfn = actual_filename;
726 include_root_dir = true;
727 } else {
728 include_root_dir = false;
729 }
730 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000731 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500732 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
733 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000734 return -2;
735 }
736 Archive_Current_Size = 0;
737
738 while (i < list_size) {
739 if (TarList->at(i).thread_id == thread_id) {
740 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400741 lstat(buf, &st);
742 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500743 fs = (unsigned long long)(st.st_size);
744 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000745 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500746 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
747 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000748 return -3;
749 }
750 archive_count++;
Ethan Yonker74db1572015-10-28 12:44:49 -0500751 gui_msg(Msg("split_thread=Splitting thread ID {1} into archive {2}")(thread_id)(archive_count + 1));
Dees_Troy83bd4832013-05-04 12:39:56 +0000752 if (archive_count > 99) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500753 LOGINFO("Too many archives for thread %i\n", thread_id);
754 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000755 return -4;
756 }
757 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
758 tarfn = actual_filename;
759 if (createTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500760 LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
761 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000762 return -2;
763 }
764 Archive_Current_Size = 0;
765 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500766 Archive_Current_Size += fs;
Ethan Yonker472f5062016-02-25 13:47:30 -0600767 fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500768 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000769 }
Dees Troye0a433a2013-12-02 04:10:37 +0000770 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
771 if (addFile(buf, include_root_dir) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500772 LOGINFO("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
773 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000774 return -1;
775 }
776 }
777 i++;
778 }
779 if (closeTar() != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500780 LOGINFO("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
781 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000782 return -3;
783 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600784 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000785 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500786}
787
Dees_Troy83bd4832013-05-04 12:39:56 +0000788void* twrpTar::createList(void *cookie) {
789
790 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600791 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000792 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
793 return (void*)-2;
794 }
795 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
796 return (void*)0;
797}
798
799void* twrpTar::extractMulti(void *cookie) {
800
801 twrpTar* threadTar = (twrpTar*) cookie;
802 int archive_count = 0;
803 string temp = threadTar->basefn + "%i%02i";
804 char actual_filename[255];
805 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
806 while (TWFunc::Path_Exists(actual_filename)) {
807 threadTar->tarfn = actual_filename;
808 if (threadTar->extract() != 0) {
809 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
810 return (void*)-2;
811 }
812 archive_count++;
813 if (archive_count > 99)
814 break;
815 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
816 }
817 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
818 return (void*)0;
819}
820
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500821int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
822 char* charTarFile = (char*) fn.c_str();
823
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200824 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500825 return -1;
826 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200827 if (tar_open(&t, charTarFile, NULL, O_WRONLY | O_APPEND | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500828 return -1;
829 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500830 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500831 if (tar_append_file(t, file, file) == -1)
832 return -1;
833 }
834 if (tar_append_eof(t) == -1)
835 return -1;
836 if (tar_close(t) == -1)
837 return -1;
838 return 0;
839}
840
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500841int twrpTar::createTar() {
842 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000843 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500844
Dees_Troy83bd4832013-05-04 12:39:56 +0000845 if (use_encryption && use_compression) {
846 // Compressed and encrypted
847 Archive_Current_Type = 3;
848 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000849 int i, pipes[4];
850
851 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500852 LOGINFO("Error creating first pipe\n");
853 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500854 return -1;
855 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000856 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500857 LOGINFO("Error creating second pipe\n");
858 gui_err("backup_error=Error creating backup.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500859 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000860 }
Dees Troy9d723272014-04-07 17:13:10 +0000861 int 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);
862 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500863 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000864 for (i = 0; i < 4; i++)
865 close(pipes[i]); // close all
866 return -1;
867 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000868 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400869
Dees_Troy83bd4832013-05-04 12:39:56 +0000870 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500871 LOGINFO("pigz fork() failed\n");
872 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000873 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000874 for (i = 0; i < 4; i++)
875 close(pipes[i]); // close all
876 return -1;
877 } else if (pigz_pid == 0) {
878 // pigz Child
879 close(pipes[1]);
880 close(pipes[2]);
881 close(0);
882 dup2(pipes[0], 0);
883 close(1);
884 dup2(pipes[3], 1);
885 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500886 LOGINFO("execlp pigz ERROR!\n");
887 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000888 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000889 close(pipes[0]);
890 close(pipes[3]);
891 _exit(-1);
892 }
893 } else {
894 // Parent
895 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400896
Dees_Troy83bd4832013-05-04 12:39:56 +0000897 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500898 LOGINFO("openaes fork() failed\n");
899 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000900 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000901 for (i = 0; i < 4; i++)
902 close(pipes[i]); // close all
903 return -1;
904 } else if (oaes_pid == 0) {
905 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000906 close(pipes[0]);
907 close(pipes[1]);
908 close(pipes[3]);
909 close(0);
910 dup2(pipes[2], 0);
911 close(1);
912 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600913 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500914 LOGINFO("execlp openaes ERROR!\n");
915 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000916 close(pipes[2]);
917 close(output_fd);
918 _exit(-1);
919 }
920 } else {
921 // Parent
922 close(pipes[0]);
923 close(pipes[2]);
924 close(pipes[3]);
925 fd = pipes[1];
Ethan Yonker472f5062016-02-25 13:47:30 -0600926 init_libtar_no_buffer(progress_pipe_fd);
927 tar_type = { open, close, read, write_tar_no_buffer };
928 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, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000929 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500930 LOGINFO("tar_fdopen failed\n");
931 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000932 return -1;
933 }
934 return 0;
935 }
936 }
937 } else if (use_compression) {
938 // Compressed
939 Archive_Current_Type = 1;
940 LOGINFO("Using compression...\n");
941 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000942 int 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);
943 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500944 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000945 close(pigzfd[0]);
946 return -1;
947 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000948
949 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500950 LOGINFO("Error creating pipe\n");
951 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +0000952 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000953 return -1;
954 }
955 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400956
Dees_Troy83bd4832013-05-04 12:39:56 +0000957 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500958 LOGINFO("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 close(pigzfd[0]);
962 close(pigzfd[1]);
963 return -1;
964 } else if (pigz_pid == 0) {
965 // Child
966 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000967 dup2(pigzfd[0], 0); // remap stdin
968 dup2(output_fd, 1); // remap stdout to output file
969 if (execlp("pigz", "pigz", "-", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500970 LOGINFO("execlp pigz ERROR!\n");
971 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000972 close(output_fd);
973 close(pigzfd[0]);
974 _exit(-1);
975 }
976 } else {
977 // Parent
978 close(pigzfd[0]); // close parent input
979 fd = pigzfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -0600980 init_libtar_no_buffer(progress_pipe_fd);
981 tar_type = { open, close, read, write_tar_no_buffer };
982 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, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000983 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -0500984 LOGINFO("tar_fdopen failed\n");
985 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +0000986 return -1;
987 }
988 }
989 } else if (use_encryption) {
990 // Encrypted
991 Archive_Current_Type = 2;
992 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000993 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000994 int 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);
995 if (output_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -0500996 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +0000997 return -1;
998 }
999 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001000 LOGINFO("Error creating pipe\n");
1001 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001002 close(output_fd);
1003 return -1;
1004 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001005 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001006
Dees_Troy83bd4832013-05-04 12:39:56 +00001007 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001008 LOGINFO("fork() failed\n");
1009 gui_err("backup_error=Error creating backup.");
Dees Troy9d723272014-04-07 17:13:10 +00001010 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001011 close(oaesfd[0]);
1012 close(oaesfd[1]);
1013 return -1;
1014 } else if (oaes_pid == 0) {
1015 // Child
1016 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +00001017 dup2(oaesfd[0], 0); // remap stdin
1018 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -06001019 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001020 LOGINFO("execlp openaes ERROR!\n");
1021 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001022 close(output_fd);
1023 close(oaesfd[0]);
1024 _exit(-1);
1025 }
1026 } else {
1027 // Parent
1028 close(oaesfd[0]); // close parent input
1029 fd = oaesfd[1]; // copy parent output
Ethan Yonker472f5062016-02-25 13:47:30 -06001030 init_libtar_no_buffer(progress_pipe_fd);
1031 tar_type = { open, close, read, write_tar_no_buffer };
1032 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, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001033 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001034 LOGINFO("tar_fdopen failed\n");
1035 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001036 return -1;
1037 }
1038 return 0;
1039 }
1040 } else {
1041 // Not compressed or encrypted
Ethan Yonker472f5062016-02-25 13:47:30 -06001042 init_libtar_buffer(0, progress_pipe_fd);
1043 tar_type = { open, close, read, write_tar };
1044 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, TAR_GNU | TAR_STORE_SELINUX) == -1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001045 LOGINFO("tar_open error opening '%s'\n", tarfn.c_str());
1046 gui_err("backup_error=Error creating backup.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001047 return -1;
1048 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001049 }
1050 return 0;
1051}
1052
Dees_Troy83bd4832013-05-04 12:39:56 +00001053int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001054 char* charRootDir = (char*) tardir.c_str();
1055 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001056 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001057
Dees_Troy83bd4832013-05-04 12:39:56 +00001058 if (Archive_Current_Type == 3) {
1059 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001060 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001061 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1062 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001063 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001064 return -1;
1065 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001066
1067 if (pipe(pipes) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001068 LOGINFO("Error creating first pipe\n");
1069 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001070 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001071 return -1;
1072 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001073 if (pipe(pipes + 2) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001074 LOGINFO("Error creating second pipe\n");
1075 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001076 close(pipes[0]);
1077 close(pipes[1]);
1078 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001079 return -1;
1080 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001081 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001082
Dees_Troy83bd4832013-05-04 12:39:56 +00001083 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001084 LOGINFO("pigz fork() failed\n");
1085 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001086 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001087 for (i = 0; i < 4; i++)
1088 close(pipes[i]); // close all
1089 return -1;
1090 } else if (oaes_pid == 0) {
1091 // openaes Child
1092 close(pipes[0]); // Close pipes that are not used by this child
1093 close(pipes[2]);
1094 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001095 close(0);
1096 dup2(input_fd, 0);
1097 close(1);
1098 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001099 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001100 LOGINFO("execlp openaes ERROR!\n");
1101 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001102 close(input_fd);
1103 close(pipes[1]);
1104 _exit(-1);
1105 }
1106 } else {
1107 // Parent
1108 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001109
Dees_Troy83bd4832013-05-04 12:39:56 +00001110 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001111 LOGINFO("openaes fork() failed\n");
1112 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001113 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001114 for (i = 0; i < 4; i++)
1115 close(pipes[i]); // close all
1116 return -1;
1117 } else if (pigz_pid == 0) {
1118 // pigz Child
1119 close(pipes[1]); // Close pipes not used by this child
1120 close(pipes[2]);
1121 close(0);
1122 dup2(pipes[0], 0);
1123 close(1);
1124 dup2(pipes[3], 1);
1125 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001126 LOGINFO("execlp pigz ERROR!\n");
1127 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001128 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001129 close(pipes[0]);
1130 close(pipes[3]);
1131 _exit(-1);
1132 }
1133 } else {
1134 // Parent
1135 close(pipes[0]); // Close pipes not used by parent
1136 close(pipes[1]);
1137 close(pipes[3]);
1138 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001139 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001140 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001141 LOGINFO("tar_fdopen failed\n");
1142 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001143 return -1;
1144 }
1145 }
1146 }
1147 } else if (Archive_Current_Type == 2) {
1148 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001149 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001150 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1151 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001152 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001153 return -1;
1154 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001155
Dees Troy9d723272014-04-07 17:13:10 +00001156 if (pipe(oaesfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001157 LOGINFO("Error creating pipe\n");
1158 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001159 close(input_fd);
1160 return -1;
1161 }
1162
Dees_Troy83bd4832013-05-04 12:39:56 +00001163 oaes_pid = fork();
1164 if (oaes_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001165 LOGINFO("fork() failed\n");
1166 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001167 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001168 close(oaesfd[0]);
1169 close(oaesfd[1]);
1170 return -1;
1171 } else if (oaes_pid == 0) {
1172 // Child
1173 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001174 close(0); // close stdin
1175 dup2(oaesfd[1], 1); // remap stdout
1176 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001177 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001178 LOGINFO("execlp openaes ERROR!\n");
1179 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001180 close(input_fd);
1181 close(oaesfd[1]);
1182 _exit(-1);
1183 }
1184 } else {
1185 // Parent
1186 close(oaesfd[1]); // close parent output
1187 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001188 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001189 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001190 LOGINFO("tar_fdopen failed\n");
1191 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001192 return -1;
1193 }
1194 }
1195 } else if (Archive_Current_Type == 1) {
1196 LOGINFO("Opening as a gzip...\n");
1197 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001198 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1199 if (input_fd < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001200 gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno)));
Dees Troy9d723272014-04-07 17:13:10 +00001201 return -1;
1202 }
1203 if (pipe(pigzfd) < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001204 LOGINFO("Error creating pipe\n");
1205 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001206 close(input_fd);
1207 return -1;
1208 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001209
1210 pigz_pid = fork();
1211 if (pigz_pid < 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001212 LOGINFO("fork() failed\n");
1213 gui_err("restore_error=Error during restore process.");
Dees Troy9d723272014-04-07 17:13:10 +00001214 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001215 close(pigzfd[0]);
1216 close(pigzfd[1]);
1217 return -1;
1218 } else if (pigz_pid == 0) {
1219 // Child
1220 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001221 dup2(input_fd, 0); // remap input fd to stdin
1222 dup2(pigzfd[1], 1); // remap stdout
1223 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1224 close(pigzfd[1]);
1225 close(input_fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001226 LOGINFO("execlp openaes ERROR!\n");
1227 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001228 _exit(-1);
1229 }
1230 } else {
1231 // Parent
1232 close(pigzfd[1]); // close parent output
1233 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001234 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001235 close(fd);
Ethan Yonker74db1572015-10-28 12:44:49 -05001236 LOGINFO("tar_fdopen failed\n");
1237 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001238 return -1;
1239 }
1240 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001241 } else if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001242 LOGINFO("Unable to open tar archive '%s'\n", charTarFile);
1243 gui_err("restore_error=Error during restore process.");
Dees_Troy83bd4832013-05-04 12:39:56 +00001244 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001245 }
1246 return 0;
1247}
1248
1249string twrpTar::Strip_Root_Dir(string Path) {
1250 string temp;
1251 size_t slash;
1252
1253 if (Path.substr(0, 1) == "/")
1254 temp = Path.substr(1, Path.size() - 1);
1255 else
1256 temp = Path;
1257 slash = temp.find("/");
1258 if (slash == string::npos)
1259 return temp;
1260 else {
1261 string stripped;
1262
1263 stripped = temp.substr(slash, temp.size() - slash);
1264 return stripped;
1265 }
1266 return temp;
1267}
1268
1269int twrpTar::addFile(string fn, bool include_root) {
1270 char* charTarFile = (char*) fn.c_str();
1271 if (include_root) {
1272 if (tar_append_file(t, charTarFile, NULL) == -1)
1273 return -1;
1274 } else {
1275 string temp = Strip_Root_Dir(fn);
1276 char* charTarPath = (char*) temp.c_str();
1277 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1278 return -1;
1279 }
1280 return 0;
1281}
1282
Dees_Troy83bd4832013-05-04 12:39:56 +00001283int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001284 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001285 if (tar_append_eof(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001286 LOGINFO("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001287 tar_close(t);
1288 return -1;
1289 }
1290 if (tar_close(t) != 0) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001291 LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001292 return -1;
1293 }
Dees_Troy2727b992013-08-14 20:09:30 +00001294 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001295 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001296 int status;
1297 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1298 return -1;
1299 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1300 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001301 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001302 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001303 if (use_compression && !use_encryption) {
1304 string gzname = tarfn + ".gz";
1305 if (TWFunc::Path_Exists(gzname)) {
1306 rename(gzname.c_str(), tarfn.c_str());
1307 }
1308 }
1309 if (TWFunc::Get_File_Size(tarfn) == 0) {
Matt Mower3c366972015-12-25 19:28:31 -06001310 gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn));
Dees Troye0a433a2013-12-02 04:10:37 +00001311 return -1;
1312 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001313#ifndef BUILD_TWRPTAR_MAIN
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06001314 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001315#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001316 return 0;
1317}
1318
1319int twrpTar::removeEOT(string tarFile) {
1320 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001321 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001322 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001323 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001324 tar_skip_regfile(t);
1325 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001326 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001327 if (tar_close(t) == -1)
1328 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001329 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001330 return -1;
1331 return 0;
1332}
1333
n0d33b511632013-03-06 21:14:15 +02001334int twrpTar::entryExists(string entry) {
1335 char* searchstr = (char*)entry.c_str();
1336 int ret;
1337
Dees_Troy83bd4832013-05-04 12:39:56 +00001338 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001339
Dees_Troy83bd4832013-05-04 12:39:56 +00001340 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001341 ret = 0;
1342 else
1343 ret = tar_find(t, searchstr);
1344
Dees_Troy83bd4832013-05-04 12:39:56 +00001345 if (closeTar() != 0)
1346 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001347
1348 return ret;
1349}
1350
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001351unsigned long long twrpTar::get_size() {
1352 if (TWFunc::Path_Exists(tarfn)) {
1353 LOGINFO("Single archive\n");
1354 int type = 0;
1355 return uncompressedSize(tarfn, &type);
1356 } else {
1357 LOGINFO("Multiple archives\n");
1358 string temp;
1359 char actual_filename[255];
1360 int archive_count = 0, i, type = 0, temp_type = 0;
1361 unsigned long long total_restore_size = 0;
1362
1363 basefn = tarfn;
1364 temp = basefn + "%i%02i";
1365 tarfn += "000";
1366 thread_id = 0;
1367 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1368 if (!TWFunc::Path_Exists(actual_filename)) {
1369 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1370 return 0;
1371 }
1372 for (i = 0; i < 9; i++) {
1373 archive_count = 0;
1374 sprintf(actual_filename, temp.c_str(), i, archive_count);
1375 while (TWFunc::Path_Exists(actual_filename)) {
1376 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1377 if (temp_type > type)
1378 type = temp_type;
1379 archive_count++;
1380 if (archive_count > 99)
1381 break;
1382 sprintf(actual_filename, temp.c_str(), i, archive_count);
1383 }
1384 }
1385#ifndef BUILD_TWRPTAR_MAIN
1386 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1387 backup_info.SetValue("backup_size", total_restore_size);
1388 backup_info.SetValue("backup_type", type);
1389 backup_info.SaveValues();
1390#endif //ndef BUILD_TWRPTAR_MAIN
1391 return total_restore_size;
1392 }
1393 return 0;
1394}
1395
1396unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1397 int type = 0;
1398 unsigned long long total_size = 0;
1399 string Tar, Command, result;
1400 vector<string> split;
1401
1402 Tar = TWFunc::Get_Filename(filename);
1403 type = TWFunc::Get_File_Type(filename);
1404 if (type == 0) {
1405 total_size = TWFunc::Get_File_Size(filename);
1406 *archive_type = 0;
1407 } else if (type == 1) {
1408 // Compressed
1409 Command = "pigz -l '" + filename + "'";
1410 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1411 we get the uncompressed size at once. */
1412 TWFunc::Exec_Cmd(Command, result);
1413 if (!result.empty()) {
1414 /* Expected output:
1415 compressed original reduced name
1416 95855838 179403776 -1.3% data.yaffs2.win
1417 ^
1418 split[5]
1419 */
1420 split = TWFunc::split_string(result, ' ', true);
1421 if (split.size() > 4)
1422 total_size = atoi(split[5].c_str());
1423 }
1424 *archive_type = 1;
1425 } else if (type == 2) {
1426 // File is encrypted and may be compressed
1427 int ret = TWFunc::Try_Decrypting_File(filename, password);
1428 *archive_type = 2;
1429 if (ret < 1) {
Ethan Yonker74db1572015-10-28 12:44:49 -05001430 gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn));
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001431 total_size = TWFunc::Get_File_Size(filename);
1432 } else if (ret == 1) {
1433 LOGERR("Decrypted file is not in tar format.\n");
1434 total_size = TWFunc::Get_File_Size(filename);
1435 } else if (ret == 3) {
1436 *archive_type = 3;
1437 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1438 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1439 we get the uncompressed size at once. */
1440 TWFunc::Exec_Cmd(Command, result);
1441 if (!result.empty()) {
1442 LOGINFO("result was: '%s'\n", result.c_str());
1443 /* Expected output:
1444 compressed original reduced name
1445 95855838 179403776 -1.3% data.yaffs2.win
1446 ^
1447 split[5]
1448 */
1449 split = TWFunc::split_string(result, ' ', true);
1450 if (split.size() > 4)
1451 total_size = atoi(split[5].c_str());
1452 }
1453 } else {
1454 total_size = TWFunc::Get_File_Size(filename);
1455 }
1456 }
1457
1458 return total_size;
1459}
1460
Dees_Troye34c1332013-02-06 19:13:00 +00001461extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1462 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001463}
Ethan Yonker472f5062016-02-25 13:47:30 -06001464
1465extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) {
1466 return (ssize_t) write_libtar_no_buffer(fd, buffer, size);
1467}