blob: b6e4410ae7685c1c4a72d75552885fb69d4a14da [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05003 Copyright 2013 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 Yonker1b7a31b2014-07-03 15:09:22 -050045#ifndef BUILD_TWRPTAR_MAIN
46#include "data.hpp"
47#include "infomanager.hpp"
Ethan Yonker960f0302014-12-21 21:54:00 -060048extern "C" {
49 #include "set_metadata.h"
50}
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050051#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050052
53using namespace std;
54
Dees_Troy83bd4832013-05-04 12:39:56 +000055twrpTar::twrpTar(void) {
56 use_encryption = 0;
57 userdata_encryption = 0;
58 use_compression = 0;
59 split_archives = 0;
60 has_data_media = 0;
61 pigz_pid = 0;
62 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000063 Total_Backup_Size = 0;
Ethan Yonker1a147a42015-02-27 13:14:44 -060064 Archive_Current_Size = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000065 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000066}
67
68twrpTar::~twrpTar(void) {
69 // Do nothing
70}
71
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050072void twrpTar::setfn(string fn) {
73 tarfn = fn;
74}
75
76void twrpTar::setdir(string dir) {
77 tardir = dir;
78}
79
Dees Troye0a433a2013-12-02 04:10:37 +000080void twrpTar::setsize(unsigned long long backup_size) {
81 Total_Backup_Size = backup_size;
82}
83
Ethan Yonker87af5632014-02-10 11:56:35 -060084void twrpTar::setpassword(string pass) {
85 password = pass;
86}
87
bigbiff7abc5fe2015-01-17 16:53:12 -050088void twrpTar::Signal_Kill(int signum) {
89 _exit(255);
90}
91
92int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &fork_pid) {
Dees_Troy83bd4832013-05-04 12:39:56 +000093 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -050094 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050095 int progress_pipe[2], ret;
96
97 file_count = 0;
98
99 if (pipe(progress_pipe) < 0) {
100 LOGERR("Error creating progress tracking pipe\n");
101 return -1;
102 }
bigbiff7abc5fe2015-01-17 16:53:12 -0500103 if ((tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000104 LOGINFO("create tar failed to fork.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500105 close(progress_pipe[0]);
106 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500107 return -1;
108 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500109
bigbiff7abc5fe2015-01-17 16:53:12 -0500110 if (tar_fork_pid == 0) {
111 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500112 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500113 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500114 close(progress_pipe[0]);
115 progress_pipe_fd = progress_pipe[1];
116
Dees_Troy83bd4832013-05-04 12:39:56 +0000117 if (use_encryption || userdata_encryption) {
118 LOGINFO("Using encryption\n");
119 DIR* d;
120 struct dirent* de;
that2252d242015-04-03 22:33:04 +0200121 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, total_size;
122 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1, core_count = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000123 int item_len, ret, thread_error = 0;
124 std::vector<TarListStruct> RegularList;
125 std::vector<TarListStruct> EncryptList;
126 string FileName;
127 struct TarListStruct TarItem;
128 twrpTar reg, enc[9];
129 struct stat st;
130 pthread_t enc_thread[9];
131 pthread_attr_t tattr;
132 void *thread_return;
133
134 core_count = sysconf(_SC_NPROCESSORS_CONF);
135 if (core_count > 8)
136 core_count = 8;
that2252d242015-04-03 22:33:04 +0200137 LOGINFO(" Core Count : %u\n", core_count);
Dees_Troy83bd4832013-05-04 12:39:56 +0000138 Archive_Current_Size = 0;
139
140 d = opendir(tardir.c_str());
141 if (d == NULL) {
142 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500143 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000144 _exit(-1);
145 }
146 // Figure out the size of all data to be encrypted and create a list of unencrypted files
147 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500148 FileName = tardir + "/" + de->d_name;
149
150 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000151 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500152 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000153 item_len = strlen(de->d_name);
154 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 -0500155 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
156 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000157 LOGERR("Error in Generate_TarList with regular list!\n");
158 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500159 close(progress_pipe_fd);
160 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000161 _exit(-1);
162 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500163 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500164 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000165 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500166 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000167 }
168 } else if (de->d_type == DT_REG) {
169 stat(FileName.c_str(), &st);
170 encrypt_size += (unsigned long long)(st.st_size);
171 }
172 }
173 closedir(d);
174
175 target_size = encrypt_size / core_count;
176 target_size++;
177 LOGINFO(" Unencrypted size: %llu\n", regular_size);
178 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
179 LOGINFO(" Target size : %llu\n", target_size);
180 if (!userdata_encryption) {
181 enc_thread_id = 0;
182 start_thread_id = 0;
183 core_count--;
184 }
185 Archive_Current_Size = 0;
186
187 d = opendir(tardir.c_str());
188 if (d == NULL) {
189 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500190 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000191 _exit(-1);
192 }
193 // Divide up the encrypted file list for threading
194 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500195 FileName = tardir + "/" + de->d_name;
196
197 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000198 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500199 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000200 item_len = strlen(de->d_name);
201 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
202 // Do nothing, we added these to RegularList earlier
203 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500204 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500205 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
206 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000207 LOGERR("Error in Generate_TarList with encrypted list!\n");
208 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500209 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000210 _exit(-1);
211 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500212 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000213 }
214 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
215 stat(FileName.c_str(), &st);
216 if (de->d_type == DT_REG)
217 Archive_Current_Size += (unsigned long long)(st.st_size);
218 TarItem.fn = FileName;
219 TarItem.thread_id = enc_thread_id;
220 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500221 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000222 }
223 }
224 closedir(d);
225 if (enc_thread_id != core_count) {
that2252d242015-04-03 22:33:04 +0200226 LOGERR("Error dividing up threads for encryption, %u threads for %u cores!\n", enc_thread_id, core_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500227 if (enc_thread_id > core_count) {
228 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000229 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500230 } else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000231 LOGERR("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500232 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000233 }
234
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500235 // Send file count to parent
236 write(progress_pipe_fd, &file_count, sizeof(file_count));
237 // Send backup size to parent
238 total_size = regular_size + encrypt_size;
239 write(progress_pipe_fd, &total_size, sizeof(total_size));
240
Dees_Troy83bd4832013-05-04 12:39:56 +0000241 if (userdata_encryption) {
242 // Create a backup of unencrypted data
243 reg.setfn(tarfn);
244 reg.ItemList = &RegularList;
245 reg.thread_id = 0;
246 reg.use_encryption = 0;
247 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000248 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500249 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000250 LOGINFO("Creating unencrypted backup...\n");
251 if (createList((void*)&reg) != 0) {
252 LOGERR("Error creating unencrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500253 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000254 _exit(-1);
255 }
256 }
257
258 if (pthread_attr_init(&tattr)) {
259 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500260 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000261 _exit(-1);
262 }
263 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
264 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500265 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000266 _exit(-1);
267 }
268 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
269 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500270 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000271 _exit(-1);
272 }
273 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
274 LOGERR("Error setting pthread_attr_setstacksize\n");
275 _exit(-1);
276 }*/
277
278 // Create threads for the divided up encryption lists
279 for (i = start_thread_id; i <= core_count; i++) {
280 enc[i].setdir(tardir);
281 enc[i].setfn(tarfn);
282 enc[i].ItemList = &EncryptList;
283 enc[i].thread_id = i;
284 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500285 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000286 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000287 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500288 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000289 LOGINFO("Start encryption thread %i\n", i);
290 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
291 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500292 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 +0000293 if (createList((void*)&enc[i]) != 0) {
294 LOGERR("Error creating encrypted backup %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500295 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000296 _exit(-1);
297 } else {
298 enc[i].thread_id = i + 1;
299 }
300 }
301 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
302 }
303 if (pthread_attr_destroy(&tattr)) {
304 LOGERR("Failed to pthread_attr_destroy\n");
305 }
306 for (i = start_thread_id; i <= core_count; i++) {
307 if (enc[i].thread_id == i) {
308 if (pthread_join(enc_thread[i], &thread_return)) {
309 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500310 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000311 _exit(-1);
312 } else {
313 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200314 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000315 if (ret != 0) {
316 thread_error = 1;
317 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500318 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 _exit(-1);
320 }
321 }
322 } else {
323 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
324 }
325 }
326 if (thread_error) {
327 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500328 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000329 _exit(-1);
330 }
331 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500332 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000333 _exit(0);
334 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500335 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000336 std::vector<TarListStruct> FileList;
337 unsigned thread_id = 0;
338 unsigned long long target_size = 0;
339 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500340 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000341
342 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500343 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
344 if (ret < 0) {
Dees Troye0a433a2013-12-02 04:10:37 +0000345 LOGERR("Error in Generate_TarList!\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500346 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000347 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000348 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500349 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000350 // Create a backup
351 reg.setfn(tarfn);
352 reg.ItemList = &FileList;
353 reg.thread_id = 0;
354 reg.use_encryption = 0;
355 reg.use_compression = use_compression;
356 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500357 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000358 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
359 gui_print("Breaking backup file into multiple archives...\n");
360 reg.split_archives = 1;
361 } else {
362 reg.split_archives = 0;
363 }
364 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500365 write(progress_pipe_fd, &file_count, sizeof(file_count));
366 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000367 if (createList((void*)&reg) != 0) {
368 LOGERR("Error creating backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500369 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000370 _exit(-1);
371 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500372 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000373 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000374 }
375 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500376 // Parent side
377 unsigned long long fs, size_backup, files_backup, total_backup_size;
378 int first_data = 0;
379 double display_percent, progress_percent;
380 char file_progress[1024];
381 char size_progress[1024];
382 files_backup = 0;
383 size_backup = 0;
384
bigbiff7abc5fe2015-01-17 16:53:12 -0500385 fork_pid = tar_fork_pid;
386
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500387 // Parent closes output side
388 close(progress_pipe[1]);
389
390 // Read progress data from children
391 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
392 if (first_data == 0) {
393 // First incoming data is the file count
394 file_count = fs;
395 if (file_count == 0) file_count = 1; // prevent division by 0 below
396 first_data = 1;
397 } else if (first_data == 1) {
398 // Second incoming data is total size
399 total_backup_size = fs;
400 first_data = 2;
401 } else {
402 files_backup++;
403 size_backup += fs;
404 display_percent = (double)(files_backup) / (double)(file_count) * 100;
405 sprintf(file_progress, "%llu of %llu files, %i%%", files_backup, file_count, (int)(display_percent));
406#ifndef BUILD_TWRPTAR_MAIN
407 DataManager::SetValue("tw_file_progress", file_progress);
408 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
409 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
410 DataManager::SetValue("tw_size_progress", size_progress);
411 progress_percent = (display_percent / 100);
412 DataManager::SetProgress((float)(progress_percent));
413#endif //ndef BUILD_TWRPTAR_MAIN
414 }
415 }
416 close(progress_pipe[0]);
417#ifndef BUILD_TWRPTAR_MAIN
418 DataManager::SetValue("tw_file_progress", "");
419 DataManager::SetValue("tw_size_progress", "");
420
421 InfoManager backup_info(backup_folder + partition_name + ".info");
422 backup_info.SetValue("backup_size", size_backup);
423 if (use_compression && use_encryption)
424 backup_info.SetValue("backup_type", 3);
425 else if (use_encryption)
426 backup_info.SetValue("backup_type", 2);
427 else if (use_compression)
428 backup_info.SetValue("backup_type", 1);
429 else
430 backup_info.SetValue("backup_type", 0);
431 backup_info.SetValue("file_count", files_backup);
432 backup_info.SaveValues();
433#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff7abc5fe2015-01-17 16:53:12 -0500434 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500435 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500436 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500437 return 0;
438}
439
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500440int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000441 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500442 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500443 int progress_pipe[2], ret;
444
445 if (pipe(progress_pipe) < 0) {
446 LOGERR("Error creating progress tracking pipe\n");
447 return -1;
448 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000449
bigbiff7abc5fe2015-01-17 16:53:12 -0500450 tar_fork_pid = fork();
451 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000452 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500453 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000454 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500455 close(progress_pipe[0]);
456 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000457 if (TWFunc::Path_Exists(tarfn)) {
458 LOGINFO("Single archive\n");
459 if (extract() != 0)
460 _exit(-1);
461 else
462 _exit(0);
463 } else {
464 LOGINFO("Multiple archives\n");
465 string temp;
466 char actual_filename[255];
467 twrpTar tars[9];
468 pthread_t tar_thread[9];
469 pthread_attr_t tattr;
Ethan Yonkerc798c9c2015-10-09 11:15:26 -0500470 unsigned thread_count = 0, i, start_thread_id = 1;
471 int ret, thread_error = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000472 void *thread_return;
473
474 basefn = tarfn;
475 temp = basefn + "%i%02i";
476 tarfn += "000";
477 if (!TWFunc::Path_Exists(tarfn)) {
478 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500479 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000480 _exit(-1);
481 }
482 if (TWFunc::Get_File_Type(tarfn) != 2) {
483 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
484 tars[0].basefn = basefn;
485 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500486 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000487 if (extractMulti((void*)&tars[0]) != 0) {
488 LOGERR("Error extracting split archive.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500489 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000490 _exit(-1);
491 }
492 } else {
493 start_thread_id = 0;
494 }
495 // Start threading encrypted restores
496 if (pthread_attr_init(&tattr)) {
497 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500498 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000499 _exit(-1);
500 }
501 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
502 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500503 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000504 _exit(-1);
505 }
506 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
507 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500508 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000509 _exit(-1);
510 }
511 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
512 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500513 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000514 _exit(-1);
515 }*/
516 for (i = start_thread_id; i < 9; i++) {
517 sprintf(actual_filename, temp.c_str(), i, 0);
518 if (TWFunc::Path_Exists(actual_filename)) {
519 thread_count++;
520 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500521 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000522 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500523 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000524 LOGINFO("Creating extract thread ID %i\n", i);
525 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
526 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500527 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 +0000528 if (extractMulti((void*)&tars[i]) != 0) {
529 LOGERR("Error extracting backup in thread %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500530 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000531 _exit(-1);
532 } else {
533 tars[i].thread_id = i + 1;
534 }
535 }
536 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
537 } else {
538 break;
539 }
540 }
541 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
542 if (tars[i].thread_id == i) {
543 if (pthread_join(tar_thread[i], &thread_return)) {
544 LOGERR("Error joining thread %i\n", i);
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 LOGINFO("Joined thread %i.\n", i);
that2252d242015-04-03 22:33:04 +0200549 ret = (int)(intptr_t)thread_return;
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 if (ret != 0) {
551 thread_error = 1;
552 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500553 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000554 _exit(-1);
555 }
556 }
557 } else {
558 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
559 }
560 }
561 if (thread_error) {
562 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500563 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000564 _exit(-1);
565 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500566 LOGINFO("Finished encrypted restore.\n");
567 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000568 _exit(0);
569 }
570 }
571 else // parent process
572 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500573 unsigned long long fs, size_backup;
574 double display_percent, progress_percent;
575 char size_progress[1024];
576 size_backup = 0;
577
578 // Parent closes output side
579 close(progress_pipe[1]);
580
581 // Read progress data from children
582 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
583 size_backup += fs;
584 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
585 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
586 progress_percent = (display_percent / 100);
587#ifndef BUILD_TWRPTAR_MAIN
588 DataManager::SetValue("tw_size_progress", size_progress);
589 DataManager::SetProgress((float)(progress_percent));
590#endif //ndef BUILD_TWRPTAR_MAIN
591 }
592 close(progress_pipe[0]);
593#ifndef BUILD_TWRPTAR_MAIN
594 DataManager::SetValue("tw_file_progress", "");
595#endif //ndef BUILD_TWRPTAR_MAIN
596 *other_backups_size += size_backup;
597
bigbiff7abc5fe2015-01-17 16:53:12 -0500598 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000599 return -1;
600 }
601 }
602 else // fork has failed
603 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500604 close(progress_pipe[0]);
605 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000606 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500607 return -1;
608 }
609 return 0;
610}
611
Dees_Troy83bd4832013-05-04 12:39:56 +0000612int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
613 DIR* d;
614 struct dirent* de;
615 struct stat st;
616 string FileName;
617 struct TarListStruct TarItem;
618 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500619 int ret, file_count;
620 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000621
Dees_Troy83bd4832013-05-04 12:39:56 +0000622 d = opendir(Path.c_str());
623 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000624 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000625 closedir(d);
626 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500627 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000628 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500629 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500630
Matt Mower50248ab2014-03-31 15:58:40 -0500631 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000632 continue;
633 TarItem.fn = FileName;
634 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500635 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000636 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500637 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
638 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500639 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500640 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000641 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
642 stat(FileName.c_str(), &st);
643 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500644 if (de->d_type == DT_REG) {
645 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000646 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500647 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000648 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
649 *thread_id = *thread_id + 1;
650 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500651 }
652 }
653 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000654 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500655 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500656}
657
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500658int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000659 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000660 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500661 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500662 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000663 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500664 return -1;
665 }
666 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000667 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500668 return -1;
669 }
670 return 0;
671}
672
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500673int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000674 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200675
676 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500677 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000678 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000679 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500680 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000681 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600682 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000683 if (ret < 1) {
684 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
685 return -1;
686 }
687 if (ret == 1) {
688 LOGERR("Decrypted file is not in tar format.\n");
689 return -1;
690 }
691 if (ret == 3) {
692 LOGINFO("Extracting encrypted and compressed tar.\n");
693 Archive_Current_Type = 3;
694 } else
695 LOGINFO("Extracting encrypted tar.\n");
696 return extractTar();
697 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000698 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500699 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500700 }
701}
702
Dees Troye0a433a2013-12-02 04:10:37 +0000703int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000704 struct stat st;
705 char buf[PATH_MAX];
706 int list_size = TarList->size(), i = 0, archive_count = 0;
707 string temp;
708 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000709 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500710 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000711
Dees Troye0a433a2013-12-02 04:10:37 +0000712 if (split_archives) {
713 basefn = tarfn;
714 temp = basefn + "%i%02i";
715 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
716 tarfn = actual_filename;
717 include_root_dir = true;
718 } else {
719 include_root_dir = false;
720 }
721 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000722 if (createTar() != 0) {
723 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
724 return -2;
725 }
726 Archive_Current_Size = 0;
727
728 while (i < list_size) {
729 if (TarList->at(i).thread_id == thread_id) {
730 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400731 lstat(buf, &st);
732 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500733 fs = (unsigned long long)(st.st_size);
734 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000735 if (closeTar() != 0) {
736 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
737 return -3;
738 }
739 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000740 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000741 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000742 LOGERR("Too many archives for thread %i\n", thread_id);
743 return -4;
744 }
745 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
746 tarfn = actual_filename;
747 if (createTar() != 0) {
748 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
749 return -2;
750 }
751 Archive_Current_Size = 0;
752 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500753 Archive_Current_Size += fs;
754 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000755 }
Dees Troye0a433a2013-12-02 04:10:37 +0000756 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
757 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000758 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
759 return -1;
760 }
761 }
762 i++;
763 }
764 if (closeTar() != 0) {
765 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
766 return -3;
767 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600768 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000769 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500770}
771
Dees_Troy83bd4832013-05-04 12:39:56 +0000772void* twrpTar::createList(void *cookie) {
773
774 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600775 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000776 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
777 return (void*)-2;
778 }
779 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
780 return (void*)0;
781}
782
783void* twrpTar::extractMulti(void *cookie) {
784
785 twrpTar* threadTar = (twrpTar*) cookie;
786 int archive_count = 0;
787 string temp = threadTar->basefn + "%i%02i";
788 char actual_filename[255];
789 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
790 while (TWFunc::Path_Exists(actual_filename)) {
791 threadTar->tarfn = actual_filename;
792 if (threadTar->extract() != 0) {
793 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
794 return (void*)-2;
795 }
796 archive_count++;
797 if (archive_count > 99)
798 break;
799 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
800 }
801 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
802 return (void*)0;
803}
804
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500805int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
806 char* charTarFile = (char*) fn.c_str();
807
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200808 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 -0500809 return -1;
810 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200811 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 -0500812 return -1;
813 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500814 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500815 if (tar_append_file(t, file, file) == -1)
816 return -1;
817 }
818 if (tar_append_eof(t) == -1)
819 return -1;
820 if (tar_close(t) == -1)
821 return -1;
822 return 0;
823}
824
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500825int twrpTar::createTar() {
826 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000827 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000828 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500829
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 if (use_encryption && use_compression) {
831 // Compressed and encrypted
832 Archive_Current_Type = 3;
833 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000834 int i, pipes[4];
835
836 if (pipe(pipes) < 0) {
837 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500838 return -1;
839 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000840 if (pipe(pipes + 2) < 0) {
841 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500842 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000843 }
Dees Troy9d723272014-04-07 17:13:10 +0000844 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);
845 if (output_fd < 0) {
846 LOGERR("Failed to open '%s'\n", tarfn.c_str());
847 for (i = 0; i < 4; i++)
848 close(pipes[i]); // close all
849 return -1;
850 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000851 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400852
Dees_Troy83bd4832013-05-04 12:39:56 +0000853 if (pigz_pid < 0) {
854 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000855 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000856 for (i = 0; i < 4; i++)
857 close(pipes[i]); // close all
858 return -1;
859 } else if (pigz_pid == 0) {
860 // pigz Child
861 close(pipes[1]);
862 close(pipes[2]);
863 close(0);
864 dup2(pipes[0], 0);
865 close(1);
866 dup2(pipes[3], 1);
867 if (execlp("pigz", "pigz", "-", NULL) < 0) {
868 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000869 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000870 close(pipes[0]);
871 close(pipes[3]);
872 _exit(-1);
873 }
874 } else {
875 // Parent
876 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400877
Dees_Troy83bd4832013-05-04 12:39:56 +0000878 if (oaes_pid < 0) {
879 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000880 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000881 for (i = 0; i < 4; i++)
882 close(pipes[i]); // close all
883 return -1;
884 } else if (oaes_pid == 0) {
885 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000886 close(pipes[0]);
887 close(pipes[1]);
888 close(pipes[3]);
889 close(0);
890 dup2(pipes[2], 0);
891 close(1);
892 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600893 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000894 LOGERR("execlp openaes ERROR!\n");
895 close(pipes[2]);
896 close(output_fd);
897 _exit(-1);
898 }
899 } else {
900 // Parent
901 close(pipes[0]);
902 close(pipes[2]);
903 close(pipes[3]);
904 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200905 if(tar_fdopen(&t, fd, charRootDir, NULL, 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 +0000906 close(fd);
907 LOGERR("tar_fdopen failed\n");
908 return -1;
909 }
910 return 0;
911 }
912 }
913 } else if (use_compression) {
914 // Compressed
915 Archive_Current_Type = 1;
916 LOGINFO("Using compression...\n");
917 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000918 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);
919 if (output_fd < 0) {
920 LOGERR("Failed to open '%s'\n", tarfn.c_str());
921 close(pigzfd[0]);
922 return -1;
923 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000924
925 if (pipe(pigzfd) < 0) {
926 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000927 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000928 return -1;
929 }
930 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400931
Dees_Troy83bd4832013-05-04 12:39:56 +0000932 if (pigz_pid < 0) {
933 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000934 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000935 close(pigzfd[0]);
936 close(pigzfd[1]);
937 return -1;
938 } else if (pigz_pid == 0) {
939 // Child
940 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000941 dup2(pigzfd[0], 0); // remap stdin
942 dup2(output_fd, 1); // remap stdout to output file
943 if (execlp("pigz", "pigz", "-", NULL) < 0) {
944 LOGERR("execlp pigz ERROR!\n");
945 close(output_fd);
946 close(pigzfd[0]);
947 _exit(-1);
948 }
949 } else {
950 // Parent
951 close(pigzfd[0]); // close parent input
952 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200953 if(tar_fdopen(&t, fd, charRootDir, NULL, 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 +0000954 close(fd);
955 LOGERR("tar_fdopen failed\n");
956 return -1;
957 }
958 }
959 } else if (use_encryption) {
960 // Encrypted
961 Archive_Current_Type = 2;
962 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000963 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000964 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);
965 if (output_fd < 0) {
966 LOGERR("Failed to open '%s'\n", tarfn.c_str());
967 return -1;
968 }
969 if (pipe(oaesfd) < 0) {
970 LOGERR("Error creating pipe\n");
971 close(output_fd);
972 return -1;
973 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000974 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400975
Dees_Troy83bd4832013-05-04 12:39:56 +0000976 if (oaes_pid < 0) {
977 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000978 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000979 close(oaesfd[0]);
980 close(oaesfd[1]);
981 return -1;
982 } else if (oaes_pid == 0) {
983 // Child
984 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000985 dup2(oaesfd[0], 0); // remap stdin
986 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600987 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000988 LOGERR("execlp openaes ERROR!\n");
989 close(output_fd);
990 close(oaesfd[0]);
991 _exit(-1);
992 }
993 } else {
994 // Parent
995 close(oaesfd[0]); // close parent input
996 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200997 if(tar_fdopen(&t, fd, charRootDir, NULL, 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 +0000998 close(fd);
999 LOGERR("tar_fdopen failed\n");
1000 return -1;
1001 }
1002 return 0;
1003 }
1004 } else {
1005 // Not compressed or encrypted
1006 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001007 if (tar_open(&t, charTarFile, &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) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001008 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1009 return -1;
1010 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001011 }
1012 return 0;
1013}
1014
Dees_Troy83bd4832013-05-04 12:39:56 +00001015int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001016 char* charRootDir = (char*) tardir.c_str();
1017 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001018 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001019
Dees_Troy83bd4832013-05-04 12:39:56 +00001020 if (Archive_Current_Type == 3) {
1021 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001022 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001023 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1024 if (input_fd < 0) {
1025 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1026 return -1;
1027 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001028
1029 if (pipe(pipes) < 0) {
1030 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001031 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001032 return -1;
1033 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001034 if (pipe(pipes + 2) < 0) {
1035 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001036 close(pipes[0]);
1037 close(pipes[1]);
1038 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001039 return -1;
1040 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001041 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001042
Dees_Troy83bd4832013-05-04 12:39:56 +00001043 if (oaes_pid < 0) {
1044 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001045 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001046 for (i = 0; i < 4; i++)
1047 close(pipes[i]); // close all
1048 return -1;
1049 } else if (oaes_pid == 0) {
1050 // openaes Child
1051 close(pipes[0]); // Close pipes that are not used by this child
1052 close(pipes[2]);
1053 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 close(0);
1055 dup2(input_fd, 0);
1056 close(1);
1057 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001058 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001059 LOGERR("execlp openaes ERROR!\n");
1060 close(input_fd);
1061 close(pipes[1]);
1062 _exit(-1);
1063 }
1064 } else {
1065 // Parent
1066 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001067
Dees_Troy83bd4832013-05-04 12:39:56 +00001068 if (pigz_pid < 0) {
1069 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001070 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001071 for (i = 0; i < 4; i++)
1072 close(pipes[i]); // close all
1073 return -1;
1074 } else if (pigz_pid == 0) {
1075 // pigz Child
1076 close(pipes[1]); // Close pipes not used by this child
1077 close(pipes[2]);
1078 close(0);
1079 dup2(pipes[0], 0);
1080 close(1);
1081 dup2(pipes[3], 1);
1082 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1083 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +00001084 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001085 close(pipes[0]);
1086 close(pipes[3]);
1087 _exit(-1);
1088 }
1089 } else {
1090 // Parent
1091 close(pipes[0]); // Close pipes not used by parent
1092 close(pipes[1]);
1093 close(pipes[3]);
1094 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001095 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 +00001096 close(fd);
1097 LOGERR("tar_fdopen failed\n");
1098 return -1;
1099 }
1100 }
1101 }
1102 } else if (Archive_Current_Type == 2) {
1103 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001104 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001105 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1106 if (input_fd < 0) {
1107 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1108 return -1;
1109 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001110
Dees Troy9d723272014-04-07 17:13:10 +00001111 if (pipe(oaesfd) < 0) {
1112 LOGERR("Error creating pipe\n");
1113 close(input_fd);
1114 return -1;
1115 }
1116
Dees_Troy83bd4832013-05-04 12:39:56 +00001117 oaes_pid = fork();
1118 if (oaes_pid < 0) {
1119 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001120 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001121 close(oaesfd[0]);
1122 close(oaesfd[1]);
1123 return -1;
1124 } else if (oaes_pid == 0) {
1125 // Child
1126 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001127 close(0); // close stdin
1128 dup2(oaesfd[1], 1); // remap stdout
1129 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001130 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001131 LOGERR("execlp openaes ERROR!\n");
1132 close(input_fd);
1133 close(oaesfd[1]);
1134 _exit(-1);
1135 }
1136 } else {
1137 // Parent
1138 close(oaesfd[1]); // close parent output
1139 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001140 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 +00001141 close(fd);
1142 LOGERR("tar_fdopen failed\n");
1143 return -1;
1144 }
1145 }
1146 } else if (Archive_Current_Type == 1) {
1147 LOGINFO("Opening as a gzip...\n");
1148 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001149 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1150 if (input_fd < 0) {
1151 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1152 return -1;
1153 }
1154 if (pipe(pigzfd) < 0) {
1155 LOGERR("Error creating pipe\n");
1156 close(input_fd);
1157 return -1;
1158 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001159
1160 pigz_pid = fork();
1161 if (pigz_pid < 0) {
1162 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001163 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001164 close(pigzfd[0]);
1165 close(pigzfd[1]);
1166 return -1;
1167 } else if (pigz_pid == 0) {
1168 // Child
1169 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001170 dup2(input_fd, 0); // remap input fd to stdin
1171 dup2(pigzfd[1], 1); // remap stdout
1172 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1173 close(pigzfd[1]);
1174 close(input_fd);
1175 LOGERR("execlp openaes ERROR!\n");
1176 _exit(-1);
1177 }
1178 } else {
1179 // Parent
1180 close(pigzfd[1]); // close parent output
1181 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001182 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 +00001183 close(fd);
1184 LOGERR("tar_fdopen failed\n");
1185 return -1;
1186 }
1187 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001188 } 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) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001189 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1190 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001191 }
1192 return 0;
1193}
1194
1195string twrpTar::Strip_Root_Dir(string Path) {
1196 string temp;
1197 size_t slash;
1198
1199 if (Path.substr(0, 1) == "/")
1200 temp = Path.substr(1, Path.size() - 1);
1201 else
1202 temp = Path;
1203 slash = temp.find("/");
1204 if (slash == string::npos)
1205 return temp;
1206 else {
1207 string stripped;
1208
1209 stripped = temp.substr(slash, temp.size() - slash);
1210 return stripped;
1211 }
1212 return temp;
1213}
1214
1215int twrpTar::addFile(string fn, bool include_root) {
1216 char* charTarFile = (char*) fn.c_str();
1217 if (include_root) {
1218 if (tar_append_file(t, charTarFile, NULL) == -1)
1219 return -1;
1220 } else {
1221 string temp = Strip_Root_Dir(fn);
1222 char* charTarPath = (char*) temp.c_str();
1223 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1224 return -1;
1225 }
1226 return 0;
1227}
1228
Dees_Troy83bd4832013-05-04 12:39:56 +00001229int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001230 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001231 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001232 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001233 tar_close(t);
1234 return -1;
1235 }
1236 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001237 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001238 return -1;
1239 }
Dees_Troy2727b992013-08-14 20:09:30 +00001240 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001241 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001242 int status;
1243 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1244 return -1;
1245 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1246 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001247 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001248 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001249 if (use_compression && !use_encryption) {
1250 string gzname = tarfn + ".gz";
1251 if (TWFunc::Path_Exists(gzname)) {
1252 rename(gzname.c_str(), tarfn.c_str());
1253 }
1254 }
1255 if (TWFunc::Get_File_Size(tarfn) == 0) {
1256 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1257 return -1;
1258 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001259#ifndef BUILD_TWRPTAR_MAIN
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06001260 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001261#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001262 return 0;
1263}
1264
1265int twrpTar::removeEOT(string tarFile) {
1266 char* charTarFile = (char*) tarFile.c_str();
Matt Mower2b18a532015-02-20 16:58:05 -06001267 off_t tarFileEnd = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001268 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001269 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001270 tar_skip_regfile(t);
1271 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001272 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001273 if (tar_close(t) == -1)
1274 return -1;
Matt Mower2b18a532015-02-20 16:58:05 -06001275 if (tarFileEnd > 0 && truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001276 return -1;
1277 return 0;
1278}
1279
n0d33b511632013-03-06 21:14:15 +02001280int twrpTar::entryExists(string entry) {
1281 char* searchstr = (char*)entry.c_str();
1282 int ret;
1283
Dees_Troy83bd4832013-05-04 12:39:56 +00001284 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001285
Dees_Troy83bd4832013-05-04 12:39:56 +00001286 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001287 ret = 0;
1288 else
1289 ret = tar_find(t, searchstr);
1290
Dees_Troy83bd4832013-05-04 12:39:56 +00001291 if (closeTar() != 0)
1292 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001293
1294 return ret;
1295}
1296
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001297unsigned long long twrpTar::get_size() {
1298 if (TWFunc::Path_Exists(tarfn)) {
1299 LOGINFO("Single archive\n");
1300 int type = 0;
1301 return uncompressedSize(tarfn, &type);
1302 } else {
1303 LOGINFO("Multiple archives\n");
1304 string temp;
1305 char actual_filename[255];
1306 int archive_count = 0, i, type = 0, temp_type = 0;
1307 unsigned long long total_restore_size = 0;
1308
1309 basefn = tarfn;
1310 temp = basefn + "%i%02i";
1311 tarfn += "000";
1312 thread_id = 0;
1313 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1314 if (!TWFunc::Path_Exists(actual_filename)) {
1315 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1316 return 0;
1317 }
1318 for (i = 0; i < 9; i++) {
1319 archive_count = 0;
1320 sprintf(actual_filename, temp.c_str(), i, archive_count);
1321 while (TWFunc::Path_Exists(actual_filename)) {
1322 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1323 if (temp_type > type)
1324 type = temp_type;
1325 archive_count++;
1326 if (archive_count > 99)
1327 break;
1328 sprintf(actual_filename, temp.c_str(), i, archive_count);
1329 }
1330 }
1331#ifndef BUILD_TWRPTAR_MAIN
1332 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1333 backup_info.SetValue("backup_size", total_restore_size);
1334 backup_info.SetValue("backup_type", type);
1335 backup_info.SaveValues();
1336#endif //ndef BUILD_TWRPTAR_MAIN
1337 return total_restore_size;
1338 }
1339 return 0;
1340}
1341
1342unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1343 int type = 0;
1344 unsigned long long total_size = 0;
1345 string Tar, Command, result;
1346 vector<string> split;
1347
1348 Tar = TWFunc::Get_Filename(filename);
1349 type = TWFunc::Get_File_Type(filename);
1350 if (type == 0) {
1351 total_size = TWFunc::Get_File_Size(filename);
1352 *archive_type = 0;
1353 } else if (type == 1) {
1354 // Compressed
1355 Command = "pigz -l '" + filename + "'";
1356 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1357 we get the uncompressed size at once. */
1358 TWFunc::Exec_Cmd(Command, result);
1359 if (!result.empty()) {
1360 /* Expected output:
1361 compressed original reduced name
1362 95855838 179403776 -1.3% data.yaffs2.win
1363 ^
1364 split[5]
1365 */
1366 split = TWFunc::split_string(result, ' ', true);
1367 if (split.size() > 4)
1368 total_size = atoi(split[5].c_str());
1369 }
1370 *archive_type = 1;
1371 } else if (type == 2) {
1372 // File is encrypted and may be compressed
1373 int ret = TWFunc::Try_Decrypting_File(filename, password);
1374 *archive_type = 2;
1375 if (ret < 1) {
1376 LOGERR("Failed to decrypt tar file '%s'\n", filename.c_str());
1377 total_size = TWFunc::Get_File_Size(filename);
1378 } else if (ret == 1) {
1379 LOGERR("Decrypted file is not in tar format.\n");
1380 total_size = TWFunc::Get_File_Size(filename);
1381 } else if (ret == 3) {
1382 *archive_type = 3;
1383 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1384 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1385 we get the uncompressed size at once. */
1386 TWFunc::Exec_Cmd(Command, result);
1387 if (!result.empty()) {
1388 LOGINFO("result was: '%s'\n", result.c_str());
1389 /* Expected output:
1390 compressed original reduced name
1391 95855838 179403776 -1.3% data.yaffs2.win
1392 ^
1393 split[5]
1394 */
1395 split = TWFunc::split_string(result, ' ', true);
1396 if (split.size() > 4)
1397 total_size = atoi(split[5].c_str());
1398 }
1399 } else {
1400 total_size = TWFunc::Get_File_Size(filename);
1401 }
1402 }
1403
1404 return total_size;
1405}
1406
Dees_Troye34c1332013-02-06 19:13:00 +00001407extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1408 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001409}