blob: dfaa541d92c867774b0d7d7f5309d64316ce49af [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;
64 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000065}
66
67twrpTar::~twrpTar(void) {
68 // Do nothing
69}
70
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050071void twrpTar::setfn(string fn) {
72 tarfn = fn;
73}
74
75void twrpTar::setdir(string dir) {
76 tardir = dir;
77}
78
Dees Troye0a433a2013-12-02 04:10:37 +000079void twrpTar::setsize(unsigned long long backup_size) {
80 Total_Backup_Size = backup_size;
81}
82
Ethan Yonker87af5632014-02-10 11:56:35 -060083void twrpTar::setpassword(string pass) {
84 password = pass;
85}
86
bigbiff7abc5fe2015-01-17 16:53:12 -050087void twrpTar::Signal_Kill(int signum) {
88 _exit(255);
89}
90
91int 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 +000092 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -050093 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050094 int progress_pipe[2], ret;
95
96 file_count = 0;
97
98 if (pipe(progress_pipe) < 0) {
99 LOGERR("Error creating progress tracking pipe\n");
100 return -1;
101 }
bigbiff7abc5fe2015-01-17 16:53:12 -0500102 if ((tar_fork_pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000103 LOGINFO("create tar failed to fork.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500104 close(progress_pipe[0]);
105 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500106 return -1;
107 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500108
bigbiff7abc5fe2015-01-17 16:53:12 -0500109 if (tar_fork_pid == 0) {
110 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500111 // Child closes input side of progress pipe
bigbiff7abc5fe2015-01-17 16:53:12 -0500112 signal(SIGUSR2, twrpTar::Signal_Kill);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500113 close(progress_pipe[0]);
114 progress_pipe_fd = progress_pipe[1];
115
Dees_Troy83bd4832013-05-04 12:39:56 +0000116 if (use_encryption || userdata_encryption) {
117 LOGINFO("Using encryption\n");
118 DIR* d;
119 struct dirent* de;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500120 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1, total_size;
Dees_Troy83bd4832013-05-04 12:39:56 +0000121 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
122 int item_len, ret, thread_error = 0;
123 std::vector<TarListStruct> RegularList;
124 std::vector<TarListStruct> EncryptList;
125 string FileName;
126 struct TarListStruct TarItem;
127 twrpTar reg, enc[9];
128 struct stat st;
129 pthread_t enc_thread[9];
130 pthread_attr_t tattr;
131 void *thread_return;
132
133 core_count = sysconf(_SC_NPROCESSORS_CONF);
134 if (core_count > 8)
135 core_count = 8;
136 LOGINFO(" Core Count : %llu\n", core_count);
137 Archive_Current_Size = 0;
138
139 d = opendir(tardir.c_str());
140 if (d == NULL) {
141 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500142 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000143 _exit(-1);
144 }
145 // Figure out the size of all data to be encrypted and create a list of unencrypted files
146 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500147 FileName = tardir + "/" + de->d_name;
148
149 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000150 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500151 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000152 item_len = strlen(de->d_name);
153 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 -0500154 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
155 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000156 LOGERR("Error in Generate_TarList with regular list!\n");
157 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500158 close(progress_pipe_fd);
159 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000160 _exit(-1);
161 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500162 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500163 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000164 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500165 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000166 }
167 } else if (de->d_type == DT_REG) {
168 stat(FileName.c_str(), &st);
169 encrypt_size += (unsigned long long)(st.st_size);
170 }
171 }
172 closedir(d);
173
174 target_size = encrypt_size / core_count;
175 target_size++;
176 LOGINFO(" Unencrypted size: %llu\n", regular_size);
177 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
178 LOGINFO(" Target size : %llu\n", target_size);
179 if (!userdata_encryption) {
180 enc_thread_id = 0;
181 start_thread_id = 0;
182 core_count--;
183 }
184 Archive_Current_Size = 0;
185
186 d = opendir(tardir.c_str());
187 if (d == NULL) {
188 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500189 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000190 _exit(-1);
191 }
192 // Divide up the encrypted file list for threading
193 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500194 FileName = tardir + "/" + de->d_name;
195
196 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000197 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500198 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000199 item_len = strlen(de->d_name);
200 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
201 // Do nothing, we added these to RegularList earlier
202 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500203 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500204 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
205 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000206 LOGERR("Error in Generate_TarList with encrypted list!\n");
207 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500208 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000209 _exit(-1);
210 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500211 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000212 }
213 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
214 stat(FileName.c_str(), &st);
215 if (de->d_type == DT_REG)
216 Archive_Current_Size += (unsigned long long)(st.st_size);
217 TarItem.fn = FileName;
218 TarItem.thread_id = enc_thread_id;
219 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500220 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000221 }
222 }
223 closedir(d);
224 if (enc_thread_id != core_count) {
225 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500226 if (enc_thread_id > core_count) {
227 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000228 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500229 } else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000230 LOGERR("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500231 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000232 }
233
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500234 // Send file count to parent
235 write(progress_pipe_fd, &file_count, sizeof(file_count));
236 // Send backup size to parent
237 total_size = regular_size + encrypt_size;
238 write(progress_pipe_fd, &total_size, sizeof(total_size));
239
Dees_Troy83bd4832013-05-04 12:39:56 +0000240 if (userdata_encryption) {
241 // Create a backup of unencrypted data
242 reg.setfn(tarfn);
243 reg.ItemList = &RegularList;
244 reg.thread_id = 0;
245 reg.use_encryption = 0;
246 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000247 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500248 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000249 LOGINFO("Creating unencrypted backup...\n");
250 if (createList((void*)&reg) != 0) {
251 LOGERR("Error creating unencrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500252 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000253 _exit(-1);
254 }
255 }
256
257 if (pthread_attr_init(&tattr)) {
258 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500259 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000260 _exit(-1);
261 }
262 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
263 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500264 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000265 _exit(-1);
266 }
267 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
268 LOGERR("Error setting pthread_attr_setscope\n");
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_setstacksize(&tattr, 524288)) {
273 LOGERR("Error setting pthread_attr_setstacksize\n");
274 _exit(-1);
275 }*/
276
277 // Create threads for the divided up encryption lists
278 for (i = start_thread_id; i <= core_count; i++) {
279 enc[i].setdir(tardir);
280 enc[i].setfn(tarfn);
281 enc[i].ItemList = &EncryptList;
282 enc[i].thread_id = i;
283 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500284 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000285 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000286 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500287 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000288 LOGINFO("Start encryption thread %i\n", i);
289 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
290 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500291 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 +0000292 if (createList((void*)&enc[i]) != 0) {
293 LOGERR("Error creating encrypted backup %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500294 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000295 _exit(-1);
296 } else {
297 enc[i].thread_id = i + 1;
298 }
299 }
300 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
301 }
302 if (pthread_attr_destroy(&tattr)) {
303 LOGERR("Failed to pthread_attr_destroy\n");
304 }
305 for (i = start_thread_id; i <= core_count; i++) {
306 if (enc[i].thread_id == i) {
307 if (pthread_join(enc_thread[i], &thread_return)) {
308 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500309 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000310 _exit(-1);
311 } else {
312 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600313 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000314 if (ret != 0) {
315 thread_error = 1;
316 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500317 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000318 _exit(-1);
319 }
320 }
321 } else {
322 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
323 }
324 }
325 if (thread_error) {
326 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500327 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000328 _exit(-1);
329 }
330 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500331 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000332 _exit(0);
333 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500334 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000335 std::vector<TarListStruct> FileList;
336 unsigned thread_id = 0;
337 unsigned long long target_size = 0;
338 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500339 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000340
341 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500342 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
343 if (ret < 0) {
Dees Troye0a433a2013-12-02 04:10:37 +0000344 LOGERR("Error in Generate_TarList!\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500345 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000346 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000347 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500348 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000349 // Create a backup
350 reg.setfn(tarfn);
351 reg.ItemList = &FileList;
352 reg.thread_id = 0;
353 reg.use_encryption = 0;
354 reg.use_compression = use_compression;
355 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500356 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000357 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
358 gui_print("Breaking backup file into multiple archives...\n");
359 reg.split_archives = 1;
360 } else {
361 reg.split_archives = 0;
362 }
363 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500364 write(progress_pipe_fd, &file_count, sizeof(file_count));
365 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000366 if (createList((void*)&reg) != 0) {
367 LOGERR("Error creating backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500368 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000369 _exit(-1);
370 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500371 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000372 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000373 }
374 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500375 // Parent side
376 unsigned long long fs, size_backup, files_backup, total_backup_size;
377 int first_data = 0;
378 double display_percent, progress_percent;
379 char file_progress[1024];
380 char size_progress[1024];
381 files_backup = 0;
382 size_backup = 0;
383
bigbiff7abc5fe2015-01-17 16:53:12 -0500384 fork_pid = tar_fork_pid;
385
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500386 // Parent closes output side
387 close(progress_pipe[1]);
388
389 // Read progress data from children
390 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
391 if (first_data == 0) {
392 // First incoming data is the file count
393 file_count = fs;
394 if (file_count == 0) file_count = 1; // prevent division by 0 below
395 first_data = 1;
396 } else if (first_data == 1) {
397 // Second incoming data is total size
398 total_backup_size = fs;
399 first_data = 2;
400 } else {
401 files_backup++;
402 size_backup += fs;
403 display_percent = (double)(files_backup) / (double)(file_count) * 100;
404 sprintf(file_progress, "%llu of %llu files, %i%%", files_backup, file_count, (int)(display_percent));
405#ifndef BUILD_TWRPTAR_MAIN
406 DataManager::SetValue("tw_file_progress", file_progress);
407 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
408 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
409 DataManager::SetValue("tw_size_progress", size_progress);
410 progress_percent = (display_percent / 100);
411 DataManager::SetProgress((float)(progress_percent));
412#endif //ndef BUILD_TWRPTAR_MAIN
413 }
414 }
415 close(progress_pipe[0]);
416#ifndef BUILD_TWRPTAR_MAIN
417 DataManager::SetValue("tw_file_progress", "");
418 DataManager::SetValue("tw_size_progress", "");
419
420 InfoManager backup_info(backup_folder + partition_name + ".info");
421 backup_info.SetValue("backup_size", size_backup);
422 if (use_compression && use_encryption)
423 backup_info.SetValue("backup_type", 3);
424 else if (use_encryption)
425 backup_info.SetValue("backup_type", 2);
426 else if (use_compression)
427 backup_info.SetValue("backup_type", 1);
428 else
429 backup_info.SetValue("backup_type", 0);
430 backup_info.SetValue("file_count", files_backup);
431 backup_info.SaveValues();
432#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff7abc5fe2015-01-17 16:53:12 -0500433 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500434 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500435 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500436 return 0;
437}
438
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500439int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000440 int status = 0;
bigbiff7abc5fe2015-01-17 16:53:12 -0500441 pid_t rc_pid, tar_fork_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500442 int progress_pipe[2], ret;
443
444 if (pipe(progress_pipe) < 0) {
445 LOGERR("Error creating progress tracking pipe\n");
446 return -1;
447 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000448
bigbiff7abc5fe2015-01-17 16:53:12 -0500449 tar_fork_pid = fork();
450 if (tar_fork_pid >= 0) // fork was successful
Dees_Troy83bd4832013-05-04 12:39:56 +0000451 {
bigbiff7abc5fe2015-01-17 16:53:12 -0500452 if (tar_fork_pid == 0) // child process
Dees_Troy83bd4832013-05-04 12:39:56 +0000453 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500454 close(progress_pipe[0]);
455 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000456 if (TWFunc::Path_Exists(tarfn)) {
457 LOGINFO("Single archive\n");
458 if (extract() != 0)
459 _exit(-1);
460 else
461 _exit(0);
462 } else {
463 LOGINFO("Multiple archives\n");
464 string temp;
465 char actual_filename[255];
466 twrpTar tars[9];
467 pthread_t tar_thread[9];
468 pthread_attr_t tattr;
469 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
470 void *thread_return;
471
472 basefn = tarfn;
473 temp = basefn + "%i%02i";
474 tarfn += "000";
475 if (!TWFunc::Path_Exists(tarfn)) {
476 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500477 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000478 _exit(-1);
479 }
480 if (TWFunc::Get_File_Type(tarfn) != 2) {
481 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
482 tars[0].basefn = basefn;
483 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500484 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000485 if (extractMulti((void*)&tars[0]) != 0) {
486 LOGERR("Error extracting split archive.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500487 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000488 _exit(-1);
489 }
490 } else {
491 start_thread_id = 0;
492 }
493 // Start threading encrypted restores
494 if (pthread_attr_init(&tattr)) {
495 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500496 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000497 _exit(-1);
498 }
499 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
500 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500501 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000502 _exit(-1);
503 }
504 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
505 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500506 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000507 _exit(-1);
508 }
509 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
510 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500511 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000512 _exit(-1);
513 }*/
514 for (i = start_thread_id; i < 9; i++) {
515 sprintf(actual_filename, temp.c_str(), i, 0);
516 if (TWFunc::Path_Exists(actual_filename)) {
517 thread_count++;
518 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500519 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000520 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500521 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000522 LOGINFO("Creating extract thread ID %i\n", i);
523 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
524 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500525 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 +0000526 if (extractMulti((void*)&tars[i]) != 0) {
527 LOGERR("Error extracting backup in thread %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500528 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000529 _exit(-1);
530 } else {
531 tars[i].thread_id = i + 1;
532 }
533 }
534 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
535 } else {
536 break;
537 }
538 }
539 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
540 if (tars[i].thread_id == i) {
541 if (pthread_join(tar_thread[i], &thread_return)) {
542 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500543 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000544 _exit(-1);
545 } else {
546 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600547 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000548 if (ret != 0) {
549 thread_error = 1;
550 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500551 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000552 _exit(-1);
553 }
554 }
555 } else {
556 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
557 }
558 }
559 if (thread_error) {
560 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500561 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000562 _exit(-1);
563 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500564 LOGINFO("Finished encrypted restore.\n");
565 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000566 _exit(0);
567 }
568 }
569 else // parent process
570 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500571 unsigned long long fs, size_backup;
572 double display_percent, progress_percent;
573 char size_progress[1024];
574 size_backup = 0;
575
576 // Parent closes output side
577 close(progress_pipe[1]);
578
579 // Read progress data from children
580 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
581 size_backup += fs;
582 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
583 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
584 progress_percent = (display_percent / 100);
585#ifndef BUILD_TWRPTAR_MAIN
586 DataManager::SetValue("tw_size_progress", size_progress);
587 DataManager::SetProgress((float)(progress_percent));
588#endif //ndef BUILD_TWRPTAR_MAIN
589 }
590 close(progress_pipe[0]);
591#ifndef BUILD_TWRPTAR_MAIN
592 DataManager::SetValue("tw_file_progress", "");
593#endif //ndef BUILD_TWRPTAR_MAIN
594 *other_backups_size += size_backup;
595
bigbiff7abc5fe2015-01-17 16:53:12 -0500596 if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0)
Dees_Troy83bd4832013-05-04 12:39:56 +0000597 return -1;
598 }
599 }
600 else // fork has failed
601 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500602 close(progress_pipe[0]);
603 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000604 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500605 return -1;
606 }
607 return 0;
608}
609
Dees_Troy83bd4832013-05-04 12:39:56 +0000610int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
611 DIR* d;
612 struct dirent* de;
613 struct stat st;
614 string FileName;
615 struct TarListStruct TarItem;
616 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500617 int ret, file_count;
618 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000619
Dees_Troy83bd4832013-05-04 12:39:56 +0000620 d = opendir(Path.c_str());
621 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000622 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000623 closedir(d);
624 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500625 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000626 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500627 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500628
Matt Mower50248ab2014-03-31 15:58:40 -0500629 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000630 continue;
631 TarItem.fn = FileName;
632 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500633 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000634 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500635 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
636 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500637 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500638 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000639 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
640 stat(FileName.c_str(), &st);
641 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500642 if (de->d_type == DT_REG) {
643 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000644 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500645 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000646 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
647 *thread_id = *thread_id + 1;
648 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500649 }
650 }
651 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000652 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500653 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500654}
655
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500656int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000657 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000658 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500659 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500660 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000661 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500662 return -1;
663 }
664 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000665 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500666 return -1;
667 }
668 return 0;
669}
670
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500671int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000672 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200673
674 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500675 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000676 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000677 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500678 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000679 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600680 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000681 if (ret < 1) {
682 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
683 return -1;
684 }
685 if (ret == 1) {
686 LOGERR("Decrypted file is not in tar format.\n");
687 return -1;
688 }
689 if (ret == 3) {
690 LOGINFO("Extracting encrypted and compressed tar.\n");
691 Archive_Current_Type = 3;
692 } else
693 LOGINFO("Extracting encrypted tar.\n");
694 return extractTar();
695 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000696 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500697 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500698 }
699}
700
Dees Troye0a433a2013-12-02 04:10:37 +0000701int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000702 struct stat st;
703 char buf[PATH_MAX];
704 int list_size = TarList->size(), i = 0, archive_count = 0;
705 string temp;
706 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000707 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500708 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000709
Dees Troye0a433a2013-12-02 04:10:37 +0000710 if (split_archives) {
711 basefn = tarfn;
712 temp = basefn + "%i%02i";
713 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
714 tarfn = actual_filename;
715 include_root_dir = true;
716 } else {
717 include_root_dir = false;
718 }
719 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000720 if (createTar() != 0) {
721 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
722 return -2;
723 }
724 Archive_Current_Size = 0;
725
726 while (i < list_size) {
727 if (TarList->at(i).thread_id == thread_id) {
728 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400729 lstat(buf, &st);
730 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500731 fs = (unsigned long long)(st.st_size);
732 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000733 if (closeTar() != 0) {
734 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
735 return -3;
736 }
737 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000738 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000739 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000740 LOGERR("Too many archives for thread %i\n", thread_id);
741 return -4;
742 }
743 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
744 tarfn = actual_filename;
745 if (createTar() != 0) {
746 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
747 return -2;
748 }
749 Archive_Current_Size = 0;
750 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500751 Archive_Current_Size += fs;
752 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000753 }
Dees Troye0a433a2013-12-02 04:10:37 +0000754 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
755 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000756 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
757 return -1;
758 }
759 }
760 i++;
761 }
762 if (closeTar() != 0) {
763 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
764 return -3;
765 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600766 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000767 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500768}
769
Dees_Troy83bd4832013-05-04 12:39:56 +0000770void* twrpTar::createList(void *cookie) {
771
772 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600773 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000774 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
775 return (void*)-2;
776 }
777 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
778 return (void*)0;
779}
780
781void* twrpTar::extractMulti(void *cookie) {
782
783 twrpTar* threadTar = (twrpTar*) cookie;
784 int archive_count = 0;
785 string temp = threadTar->basefn + "%i%02i";
786 char actual_filename[255];
787 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
788 while (TWFunc::Path_Exists(actual_filename)) {
789 threadTar->tarfn = actual_filename;
790 if (threadTar->extract() != 0) {
791 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
792 return (void*)-2;
793 }
794 archive_count++;
795 if (archive_count > 99)
796 break;
797 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
798 }
799 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
800 return (void*)0;
801}
802
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500803int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
804 char* charTarFile = (char*) fn.c_str();
805
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200806 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 -0500807 return -1;
808 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200809 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 -0500810 return -1;
811 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500812 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500813 if (tar_append_file(t, file, file) == -1)
814 return -1;
815 }
816 if (tar_append_eof(t) == -1)
817 return -1;
818 if (tar_close(t) == -1)
819 return -1;
820 return 0;
821}
822
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500823int twrpTar::createTar() {
824 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000825 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000826 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500827
Dees_Troy83bd4832013-05-04 12:39:56 +0000828 if (use_encryption && use_compression) {
829 // Compressed and encrypted
830 Archive_Current_Type = 3;
831 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000832 int i, pipes[4];
833
834 if (pipe(pipes) < 0) {
835 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500836 return -1;
837 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000838 if (pipe(pipes + 2) < 0) {
839 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500840 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000841 }
Dees Troy9d723272014-04-07 17:13:10 +0000842 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);
843 if (output_fd < 0) {
844 LOGERR("Failed to open '%s'\n", tarfn.c_str());
845 for (i = 0; i < 4; i++)
846 close(pipes[i]); // close all
847 return -1;
848 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000849 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400850
Dees_Troy83bd4832013-05-04 12:39:56 +0000851 if (pigz_pid < 0) {
852 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000853 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000854 for (i = 0; i < 4; i++)
855 close(pipes[i]); // close all
856 return -1;
857 } else if (pigz_pid == 0) {
858 // pigz Child
859 close(pipes[1]);
860 close(pipes[2]);
861 close(0);
862 dup2(pipes[0], 0);
863 close(1);
864 dup2(pipes[3], 1);
865 if (execlp("pigz", "pigz", "-", NULL) < 0) {
866 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000867 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000868 close(pipes[0]);
869 close(pipes[3]);
870 _exit(-1);
871 }
872 } else {
873 // Parent
874 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400875
Dees_Troy83bd4832013-05-04 12:39:56 +0000876 if (oaes_pid < 0) {
877 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000878 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000879 for (i = 0; i < 4; i++)
880 close(pipes[i]); // close all
881 return -1;
882 } else if (oaes_pid == 0) {
883 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000884 close(pipes[0]);
885 close(pipes[1]);
886 close(pipes[3]);
887 close(0);
888 dup2(pipes[2], 0);
889 close(1);
890 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600891 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000892 LOGERR("execlp openaes ERROR!\n");
893 close(pipes[2]);
894 close(output_fd);
895 _exit(-1);
896 }
897 } else {
898 // Parent
899 close(pipes[0]);
900 close(pipes[2]);
901 close(pipes[3]);
902 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200903 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 +0000904 close(fd);
905 LOGERR("tar_fdopen failed\n");
906 return -1;
907 }
908 return 0;
909 }
910 }
911 } else if (use_compression) {
912 // Compressed
913 Archive_Current_Type = 1;
914 LOGINFO("Using compression...\n");
915 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000916 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);
917 if (output_fd < 0) {
918 LOGERR("Failed to open '%s'\n", tarfn.c_str());
919 close(pigzfd[0]);
920 return -1;
921 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000922
923 if (pipe(pigzfd) < 0) {
924 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000925 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000926 return -1;
927 }
928 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400929
Dees_Troy83bd4832013-05-04 12:39:56 +0000930 if (pigz_pid < 0) {
931 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000932 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000933 close(pigzfd[0]);
934 close(pigzfd[1]);
935 return -1;
936 } else if (pigz_pid == 0) {
937 // Child
938 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000939 dup2(pigzfd[0], 0); // remap stdin
940 dup2(output_fd, 1); // remap stdout to output file
941 if (execlp("pigz", "pigz", "-", NULL) < 0) {
942 LOGERR("execlp pigz ERROR!\n");
943 close(output_fd);
944 close(pigzfd[0]);
945 _exit(-1);
946 }
947 } else {
948 // Parent
949 close(pigzfd[0]); // close parent input
950 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200951 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 +0000952 close(fd);
953 LOGERR("tar_fdopen failed\n");
954 return -1;
955 }
956 }
957 } else if (use_encryption) {
958 // Encrypted
959 Archive_Current_Type = 2;
960 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000961 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000962 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);
963 if (output_fd < 0) {
964 LOGERR("Failed to open '%s'\n", tarfn.c_str());
965 return -1;
966 }
967 if (pipe(oaesfd) < 0) {
968 LOGERR("Error creating pipe\n");
969 close(output_fd);
970 return -1;
971 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000972 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400973
Dees_Troy83bd4832013-05-04 12:39:56 +0000974 if (oaes_pid < 0) {
975 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000976 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000977 close(oaesfd[0]);
978 close(oaesfd[1]);
979 return -1;
980 } else if (oaes_pid == 0) {
981 // Child
982 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000983 dup2(oaesfd[0], 0); // remap stdin
984 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600985 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000986 LOGERR("execlp openaes ERROR!\n");
987 close(output_fd);
988 close(oaesfd[0]);
989 _exit(-1);
990 }
991 } else {
992 // Parent
993 close(oaesfd[0]); // close parent input
994 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200995 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 +0000996 close(fd);
997 LOGERR("tar_fdopen failed\n");
998 return -1;
999 }
1000 return 0;
1001 }
1002 } else {
1003 // Not compressed or encrypted
1004 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001005 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 +00001006 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
1007 return -1;
1008 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001009 }
1010 return 0;
1011}
1012
Dees_Troy83bd4832013-05-04 12:39:56 +00001013int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001014 char* charRootDir = (char*) tardir.c_str();
1015 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001016 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001017
Dees_Troy83bd4832013-05-04 12:39:56 +00001018 if (Archive_Current_Type == 3) {
1019 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001020 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001021 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1022 if (input_fd < 0) {
1023 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1024 return -1;
1025 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001026
1027 if (pipe(pipes) < 0) {
1028 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001029 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001030 return -1;
1031 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001032 if (pipe(pipes + 2) < 0) {
1033 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001034 close(pipes[0]);
1035 close(pipes[1]);
1036 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001037 return -1;
1038 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001039 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001040
Dees_Troy83bd4832013-05-04 12:39:56 +00001041 if (oaes_pid < 0) {
1042 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001043 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001044 for (i = 0; i < 4; i++)
1045 close(pipes[i]); // close all
1046 return -1;
1047 } else if (oaes_pid == 0) {
1048 // openaes Child
1049 close(pipes[0]); // Close pipes that are not used by this child
1050 close(pipes[2]);
1051 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001052 close(0);
1053 dup2(input_fd, 0);
1054 close(1);
1055 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001056 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001057 LOGERR("execlp openaes ERROR!\n");
1058 close(input_fd);
1059 close(pipes[1]);
1060 _exit(-1);
1061 }
1062 } else {
1063 // Parent
1064 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001065
Dees_Troy83bd4832013-05-04 12:39:56 +00001066 if (pigz_pid < 0) {
1067 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001068 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001069 for (i = 0; i < 4; i++)
1070 close(pipes[i]); // close all
1071 return -1;
1072 } else if (pigz_pid == 0) {
1073 // pigz Child
1074 close(pipes[1]); // Close pipes not used by this child
1075 close(pipes[2]);
1076 close(0);
1077 dup2(pipes[0], 0);
1078 close(1);
1079 dup2(pipes[3], 1);
1080 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1081 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +00001082 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001083 close(pipes[0]);
1084 close(pipes[3]);
1085 _exit(-1);
1086 }
1087 } else {
1088 // Parent
1089 close(pipes[0]); // Close pipes not used by parent
1090 close(pipes[1]);
1091 close(pipes[3]);
1092 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001093 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 +00001094 close(fd);
1095 LOGERR("tar_fdopen failed\n");
1096 return -1;
1097 }
1098 }
1099 }
1100 } else if (Archive_Current_Type == 2) {
1101 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001102 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001103 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1104 if (input_fd < 0) {
1105 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1106 return -1;
1107 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001108
Dees Troy9d723272014-04-07 17:13:10 +00001109 if (pipe(oaesfd) < 0) {
1110 LOGERR("Error creating pipe\n");
1111 close(input_fd);
1112 return -1;
1113 }
1114
Dees_Troy83bd4832013-05-04 12:39:56 +00001115 oaes_pid = fork();
1116 if (oaes_pid < 0) {
1117 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001118 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001119 close(oaesfd[0]);
1120 close(oaesfd[1]);
1121 return -1;
1122 } else if (oaes_pid == 0) {
1123 // Child
1124 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001125 close(0); // close stdin
1126 dup2(oaesfd[1], 1); // remap stdout
1127 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001128 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001129 LOGERR("execlp openaes ERROR!\n");
1130 close(input_fd);
1131 close(oaesfd[1]);
1132 _exit(-1);
1133 }
1134 } else {
1135 // Parent
1136 close(oaesfd[1]); // close parent output
1137 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001138 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 +00001139 close(fd);
1140 LOGERR("tar_fdopen failed\n");
1141 return -1;
1142 }
1143 }
1144 } else if (Archive_Current_Type == 1) {
1145 LOGINFO("Opening as a gzip...\n");
1146 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001147 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1148 if (input_fd < 0) {
1149 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1150 return -1;
1151 }
1152 if (pipe(pigzfd) < 0) {
1153 LOGERR("Error creating pipe\n");
1154 close(input_fd);
1155 return -1;
1156 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001157
1158 pigz_pid = fork();
1159 if (pigz_pid < 0) {
1160 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001161 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001162 close(pigzfd[0]);
1163 close(pigzfd[1]);
1164 return -1;
1165 } else if (pigz_pid == 0) {
1166 // Child
1167 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001168 dup2(input_fd, 0); // remap input fd to stdin
1169 dup2(pigzfd[1], 1); // remap stdout
1170 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1171 close(pigzfd[1]);
1172 close(input_fd);
1173 LOGERR("execlp openaes ERROR!\n");
1174 _exit(-1);
1175 }
1176 } else {
1177 // Parent
1178 close(pigzfd[1]); // close parent output
1179 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001180 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 +00001181 close(fd);
1182 LOGERR("tar_fdopen failed\n");
1183 return -1;
1184 }
1185 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001186 } 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 +00001187 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1188 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001189 }
1190 return 0;
1191}
1192
1193string twrpTar::Strip_Root_Dir(string Path) {
1194 string temp;
1195 size_t slash;
1196
1197 if (Path.substr(0, 1) == "/")
1198 temp = Path.substr(1, Path.size() - 1);
1199 else
1200 temp = Path;
1201 slash = temp.find("/");
1202 if (slash == string::npos)
1203 return temp;
1204 else {
1205 string stripped;
1206
1207 stripped = temp.substr(slash, temp.size() - slash);
1208 return stripped;
1209 }
1210 return temp;
1211}
1212
1213int twrpTar::addFile(string fn, bool include_root) {
1214 char* charTarFile = (char*) fn.c_str();
1215 if (include_root) {
1216 if (tar_append_file(t, charTarFile, NULL) == -1)
1217 return -1;
1218 } else {
1219 string temp = Strip_Root_Dir(fn);
1220 char* charTarPath = (char*) temp.c_str();
1221 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1222 return -1;
1223 }
1224 return 0;
1225}
1226
Dees_Troy83bd4832013-05-04 12:39:56 +00001227int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001228 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001229 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001230 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001231 tar_close(t);
1232 return -1;
1233 }
1234 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001235 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001236 return -1;
1237 }
Dees_Troy2727b992013-08-14 20:09:30 +00001238 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001239 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001240 int status;
1241 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1242 return -1;
1243 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1244 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001245 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001246 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001247 if (use_compression && !use_encryption) {
1248 string gzname = tarfn + ".gz";
1249 if (TWFunc::Path_Exists(gzname)) {
1250 rename(gzname.c_str(), tarfn.c_str());
1251 }
1252 }
1253 if (TWFunc::Get_File_Size(tarfn) == 0) {
1254 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1255 return -1;
1256 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001257#ifndef BUILD_TWRPTAR_MAIN
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06001258 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001259#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001260 return 0;
1261}
1262
1263int twrpTar::removeEOT(string tarFile) {
1264 char* charTarFile = (char*) tarFile.c_str();
1265 off_t tarFileEnd;
1266 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001267 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001268 tar_skip_regfile(t);
1269 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001270 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001271 if (tar_close(t) == -1)
1272 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001273 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001274 return -1;
1275 return 0;
1276}
1277
n0d33b511632013-03-06 21:14:15 +02001278int twrpTar::entryExists(string entry) {
1279 char* searchstr = (char*)entry.c_str();
1280 int ret;
1281
Dees_Troy83bd4832013-05-04 12:39:56 +00001282 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001283
Dees_Troy83bd4832013-05-04 12:39:56 +00001284 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001285 ret = 0;
1286 else
1287 ret = tar_find(t, searchstr);
1288
Dees_Troy83bd4832013-05-04 12:39:56 +00001289 if (closeTar() != 0)
1290 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001291
1292 return ret;
1293}
1294
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001295unsigned long long twrpTar::get_size() {
1296 if (TWFunc::Path_Exists(tarfn)) {
1297 LOGINFO("Single archive\n");
1298 int type = 0;
1299 return uncompressedSize(tarfn, &type);
1300 } else {
1301 LOGINFO("Multiple archives\n");
1302 string temp;
1303 char actual_filename[255];
1304 int archive_count = 0, i, type = 0, temp_type = 0;
1305 unsigned long long total_restore_size = 0;
1306
1307 basefn = tarfn;
1308 temp = basefn + "%i%02i";
1309 tarfn += "000";
1310 thread_id = 0;
1311 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1312 if (!TWFunc::Path_Exists(actual_filename)) {
1313 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1314 return 0;
1315 }
1316 for (i = 0; i < 9; i++) {
1317 archive_count = 0;
1318 sprintf(actual_filename, temp.c_str(), i, archive_count);
1319 while (TWFunc::Path_Exists(actual_filename)) {
1320 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1321 if (temp_type > type)
1322 type = temp_type;
1323 archive_count++;
1324 if (archive_count > 99)
1325 break;
1326 sprintf(actual_filename, temp.c_str(), i, archive_count);
1327 }
1328 }
1329#ifndef BUILD_TWRPTAR_MAIN
1330 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1331 backup_info.SetValue("backup_size", total_restore_size);
1332 backup_info.SetValue("backup_type", type);
1333 backup_info.SaveValues();
1334#endif //ndef BUILD_TWRPTAR_MAIN
1335 return total_restore_size;
1336 }
1337 return 0;
1338}
1339
1340unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1341 int type = 0;
1342 unsigned long long total_size = 0;
1343 string Tar, Command, result;
1344 vector<string> split;
1345
1346 Tar = TWFunc::Get_Filename(filename);
1347 type = TWFunc::Get_File_Type(filename);
1348 if (type == 0) {
1349 total_size = TWFunc::Get_File_Size(filename);
1350 *archive_type = 0;
1351 } else if (type == 1) {
1352 // Compressed
1353 Command = "pigz -l '" + filename + "'";
1354 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1355 we get the uncompressed size at once. */
1356 TWFunc::Exec_Cmd(Command, result);
1357 if (!result.empty()) {
1358 /* Expected output:
1359 compressed original reduced name
1360 95855838 179403776 -1.3% data.yaffs2.win
1361 ^
1362 split[5]
1363 */
1364 split = TWFunc::split_string(result, ' ', true);
1365 if (split.size() > 4)
1366 total_size = atoi(split[5].c_str());
1367 }
1368 *archive_type = 1;
1369 } else if (type == 2) {
1370 // File is encrypted and may be compressed
1371 int ret = TWFunc::Try_Decrypting_File(filename, password);
1372 *archive_type = 2;
1373 if (ret < 1) {
1374 LOGERR("Failed to decrypt tar file '%s'\n", filename.c_str());
1375 total_size = TWFunc::Get_File_Size(filename);
1376 } else if (ret == 1) {
1377 LOGERR("Decrypted file is not in tar format.\n");
1378 total_size = TWFunc::Get_File_Size(filename);
1379 } else if (ret == 3) {
1380 *archive_type = 3;
1381 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1382 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1383 we get the uncompressed size at once. */
1384 TWFunc::Exec_Cmd(Command, result);
1385 if (!result.empty()) {
1386 LOGINFO("result was: '%s'\n", result.c_str());
1387 /* Expected output:
1388 compressed original reduced name
1389 95855838 179403776 -1.3% data.yaffs2.win
1390 ^
1391 split[5]
1392 */
1393 split = TWFunc::split_string(result, ' ', true);
1394 if (split.size() > 4)
1395 total_size = atoi(split[5].c_str());
1396 }
1397 } else {
1398 total_size = TWFunc::Get_File_Size(filename);
1399 }
1400 }
1401
1402 return total_size;
1403}
1404
Dees_Troye34c1332013-02-06 19:13:00 +00001405extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1406 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001407}