blob: f6282e73b1ce0856bf57fdc88605851d38439e3a [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"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050024}
25#include <sys/types.h>
26#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050027#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050028#include <string.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050032#include <iostream>
33#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050034#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000035#include <vector>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050036#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040037#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050038#include <sys/mman.h>
39#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050041#include "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050042#include "twrp-functions.hpp"
43
44using namespace std;
45
Dees_Troy83bd4832013-05-04 12:39:56 +000046twrpTar::twrpTar(void) {
47 use_encryption = 0;
48 userdata_encryption = 0;
49 use_compression = 0;
50 split_archives = 0;
51 has_data_media = 0;
52 pigz_pid = 0;
53 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000054 Total_Backup_Size = 0;
55 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000056}
57
58twrpTar::~twrpTar(void) {
59 // Do nothing
60}
61
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050062void twrpTar::setfn(string fn) {
63 tarfn = fn;
64}
65
66void twrpTar::setdir(string dir) {
67 tardir = dir;
68}
69
Dees Troye0a433a2013-12-02 04:10:37 +000070void twrpTar::setsize(unsigned long long backup_size) {
71 Total_Backup_Size = backup_size;
72}
73
Ethan Yonker87af5632014-02-10 11:56:35 -060074void twrpTar::setpassword(string pass) {
75 password = pass;
76}
77
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050078int twrpTar::createTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +000079 int status = 0;
80 pid_t pid, rc_pid;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050081 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000082 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050083 return -1;
84 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050085 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +000086 // Child process
87 if (use_encryption || userdata_encryption) {
88 LOGINFO("Using encryption\n");
89 DIR* d;
90 struct dirent* de;
91 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1;
92 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
93 int item_len, ret, thread_error = 0;
94 std::vector<TarListStruct> RegularList;
95 std::vector<TarListStruct> EncryptList;
96 string FileName;
97 struct TarListStruct TarItem;
98 twrpTar reg, enc[9];
99 struct stat st;
100 pthread_t enc_thread[9];
101 pthread_attr_t tattr;
102 void *thread_return;
103
104 core_count = sysconf(_SC_NPROCESSORS_CONF);
105 if (core_count > 8)
106 core_count = 8;
107 LOGINFO(" Core Count : %llu\n", core_count);
108 Archive_Current_Size = 0;
109
110 d = opendir(tardir.c_str());
111 if (d == NULL) {
112 LOGERR("error opening '%s'\n", tardir.c_str());
113 _exit(-1);
114 }
115 // Figure out the size of all data to be encrypted and create a list of unencrypted files
116 while ((de = readdir(d)) != NULL) {
117 FileName = tardir + "/";
118 FileName += de->d_name;
119 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
120 continue; // Skip /data/media
121 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
122 continue;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100123 if (de->d_type == DT_DIR && !du.check_skip_dirs(tardir, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000124 item_len = strlen(de->d_name);
125 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
126 if (Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id) < 0) {
127 LOGERR("Error in Generate_TarList with regular list!\n");
128 closedir(d);
129 _exit(-1);
130 }
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500131 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000132 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500133 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000134 }
135 } else if (de->d_type == DT_REG) {
136 stat(FileName.c_str(), &st);
137 encrypt_size += (unsigned long long)(st.st_size);
138 }
139 }
140 closedir(d);
141
142 target_size = encrypt_size / core_count;
143 target_size++;
144 LOGINFO(" Unencrypted size: %llu\n", regular_size);
145 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
146 LOGINFO(" Target size : %llu\n", target_size);
147 if (!userdata_encryption) {
148 enc_thread_id = 0;
149 start_thread_id = 0;
150 core_count--;
151 }
152 Archive_Current_Size = 0;
153
154 d = opendir(tardir.c_str());
155 if (d == NULL) {
156 LOGERR("error opening '%s'\n", tardir.c_str());
157 _exit(-1);
158 }
159 // Divide up the encrypted file list for threading
160 while ((de = readdir(d)) != NULL) {
161 FileName = tardir + "/";
162 FileName += de->d_name;
163 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
164 continue; // Skip /data/media
165 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
166 continue;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100167 if (de->d_type == DT_DIR && !du.check_skip_dirs(tardir, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000168 item_len = strlen(de->d_name);
169 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
170 // Do nothing, we added these to RegularList earlier
171 } else {
172 FileName = tardir + "/";
173 FileName += de->d_name;
174 if (Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id) < 0) {
175 LOGERR("Error in Generate_TarList with encrypted list!\n");
176 closedir(d);
177 _exit(-1);
178 }
179 }
180 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
181 stat(FileName.c_str(), &st);
182 if (de->d_type == DT_REG)
183 Archive_Current_Size += (unsigned long long)(st.st_size);
184 TarItem.fn = FileName;
185 TarItem.thread_id = enc_thread_id;
186 EncryptList.push_back(TarItem);
187 }
188 }
189 closedir(d);
190 if (enc_thread_id != core_count) {
191 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
192 if (enc_thread_id > core_count)
193 _exit(-1);
194 else
195 LOGERR("Continuining anyway.");
196 }
197
198 if (userdata_encryption) {
199 // Create a backup of unencrypted data
200 reg.setfn(tarfn);
201 reg.ItemList = &RegularList;
202 reg.thread_id = 0;
203 reg.use_encryption = 0;
204 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000205 reg.split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000206 LOGINFO("Creating unencrypted backup...\n");
207 if (createList((void*)&reg) != 0) {
208 LOGERR("Error creating unencrypted backup.\n");
209 _exit(-1);
210 }
211 }
212
213 if (pthread_attr_init(&tattr)) {
214 LOGERR("Unable to pthread_attr_init\n");
215 _exit(-1);
216 }
217 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
218 LOGERR("Error setting pthread_attr_setdetachstate\n");
219 _exit(-1);
220 }
221 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
222 LOGERR("Error setting pthread_attr_setscope\n");
223 _exit(-1);
224 }
225 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
226 LOGERR("Error setting pthread_attr_setstacksize\n");
227 _exit(-1);
228 }*/
229
230 // Create threads for the divided up encryption lists
231 for (i = start_thread_id; i <= core_count; i++) {
232 enc[i].setdir(tardir);
233 enc[i].setfn(tarfn);
234 enc[i].ItemList = &EncryptList;
235 enc[i].thread_id = i;
236 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500237 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000238 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000239 enc[i].split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000240 LOGINFO("Start encryption thread %i\n", i);
241 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
242 if (ret) {
243 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).", i, ret);
244 if (createList((void*)&enc[i]) != 0) {
245 LOGERR("Error creating encrypted backup %i.\n", i);
246 _exit(-1);
247 } else {
248 enc[i].thread_id = i + 1;
249 }
250 }
251 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
252 }
253 if (pthread_attr_destroy(&tattr)) {
254 LOGERR("Failed to pthread_attr_destroy\n");
255 }
256 for (i = start_thread_id; i <= core_count; i++) {
257 if (enc[i].thread_id == i) {
258 if (pthread_join(enc_thread[i], &thread_return)) {
259 LOGERR("Error joining thread %i\n", i);
260 _exit(-1);
261 } else {
262 LOGINFO("Joined thread %i.\n", i);
263 ret = (int)thread_return;
264 if (ret != 0) {
265 thread_error = 1;
266 LOGERR("Thread %i returned an error %i.\n", i, ret);
267 _exit(-1);
268 }
269 }
270 } else {
271 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
272 }
273 }
274 if (thread_error) {
275 LOGERR("Error returned by one or more threads.\n");
276 _exit(-1);
277 }
278 LOGINFO("Finished encrypted backup.\n");
279 _exit(0);
280 } else {
Dees Troye0a433a2013-12-02 04:10:37 +0000281 std::vector<TarListStruct> FileList;
282 unsigned thread_id = 0;
283 unsigned long long target_size = 0;
284 twrpTar reg;
285
286 // Generate list of files to back up
287 if (Generate_TarList(tardir, &FileList, &target_size, &thread_id) < 0) {
288 LOGERR("Error in Generate_TarList!\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000289 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000290 }
291 // Create a backup
292 reg.setfn(tarfn);
293 reg.ItemList = &FileList;
294 reg.thread_id = 0;
295 reg.use_encryption = 0;
296 reg.use_compression = use_compression;
297 reg.setsize(Total_Backup_Size);
298 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
299 gui_print("Breaking backup file into multiple archives...\n");
300 reg.split_archives = 1;
301 } else {
302 reg.split_archives = 0;
303 }
304 LOGINFO("Creating backup...\n");
305 if (createList((void*)&reg) != 0) {
306 LOGERR("Error creating backup.\n");
307 _exit(-1);
308 }
309 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000310 }
311 } else {
312 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500313 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500314 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500315 return 0;
316}
317
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500318int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 int status = 0;
320 pid_t pid, rc_pid;
321
322 pid = fork();
323 if (pid >= 0) // fork was successful
324 {
325 if (pid == 0) // child process
326 {
327 if (TWFunc::Path_Exists(tarfn)) {
328 LOGINFO("Single archive\n");
329 if (extract() != 0)
330 _exit(-1);
331 else
332 _exit(0);
333 } else {
334 LOGINFO("Multiple archives\n");
335 string temp;
336 char actual_filename[255];
337 twrpTar tars[9];
338 pthread_t tar_thread[9];
339 pthread_attr_t tattr;
340 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
341 void *thread_return;
342
343 basefn = tarfn;
344 temp = basefn + "%i%02i";
345 tarfn += "000";
346 if (!TWFunc::Path_Exists(tarfn)) {
347 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
348 _exit(-1);
349 }
350 if (TWFunc::Get_File_Type(tarfn) != 2) {
351 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
352 tars[0].basefn = basefn;
353 tars[0].thread_id = 0;
354 if (extractMulti((void*)&tars[0]) != 0) {
355 LOGERR("Error extracting split archive.\n");
356 _exit(-1);
357 }
358 } else {
359 start_thread_id = 0;
360 }
361 // Start threading encrypted restores
362 if (pthread_attr_init(&tattr)) {
363 LOGERR("Unable to pthread_attr_init\n");
364 _exit(-1);
365 }
366 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
367 LOGERR("Error setting pthread_attr_setdetachstate\n");
368 _exit(-1);
369 }
370 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
371 LOGERR("Error setting pthread_attr_setscope\n");
372 _exit(-1);
373 }
374 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
375 LOGERR("Error setting pthread_attr_setstacksize\n");
376 _exit(-1);
377 }*/
378 for (i = start_thread_id; i < 9; i++) {
379 sprintf(actual_filename, temp.c_str(), i, 0);
380 if (TWFunc::Path_Exists(actual_filename)) {
381 thread_count++;
382 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500383 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000384 tars[i].thread_id = i;
385 LOGINFO("Creating extract thread ID %i\n", i);
386 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
387 if (ret) {
388 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).", i, ret);
389 if (extractMulti((void*)&tars[i]) != 0) {
390 LOGERR("Error extracting backup in thread %i.\n", i);
391 _exit(-1);
392 } else {
393 tars[i].thread_id = i + 1;
394 }
395 }
396 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
397 } else {
398 break;
399 }
400 }
401 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
402 if (tars[i].thread_id == i) {
403 if (pthread_join(tar_thread[i], &thread_return)) {
404 LOGERR("Error joining thread %i\n", i);
405 _exit(-1);
406 } else {
407 LOGINFO("Joined thread %i.\n", i);
408 ret = (int)thread_return;
409 if (ret != 0) {
410 thread_error = 1;
411 LOGERR("Thread %i returned an error %i.\n", i, ret);
412 _exit(-1);
413 }
414 }
415 } else {
416 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
417 }
418 }
419 if (thread_error) {
420 LOGERR("Error returned by one or more threads.\n");
421 _exit(-1);
422 }
423 LOGINFO("Finished encrypted backup.\n");
424 _exit(0);
425 }
426 }
427 else // parent process
428 {
429 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
430 return -1;
431 }
432 }
433 else // fork has failed
434 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000435 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500436 return -1;
437 }
438 return 0;
439}
440
Dees_Troy83bd4832013-05-04 12:39:56 +0000441int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
442 DIR* d;
443 struct dirent* de;
444 struct stat st;
445 string FileName;
446 struct TarListStruct TarItem;
447 string::size_type i;
Dees_Troy83bd4832013-05-04 12:39:56 +0000448
449 if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
450 return 0; // Skip /data/media
451
452 d = opendir(Path.c_str());
453 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000454 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000455 closedir(d);
456 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500457 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000458 while ((de = readdir(d)) != NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000459 FileName = Path + "/";
460 FileName += de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500461
Dees_Troy83bd4832013-05-04 12:39:56 +0000462 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
463 continue; // Skip /data/media
464 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
465 continue;
466 TarItem.fn = FileName;
467 TarItem.thread_id = *thread_id;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100468 if (de->d_type == DT_DIR && !du.check_skip_dirs(Path, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000469 TarList->push_back(TarItem);
470 if (Generate_TarList(FileName, TarList, Target_Size, thread_id) < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500471 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000472 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
473 stat(FileName.c_str(), &st);
474 TarList->push_back(TarItem);
475 if (de->d_type == DT_REG)
476 Archive_Current_Size += st.st_size;
477 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
478 *thread_id = *thread_id + 1;
479 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500480 }
481 }
482 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000483 closedir(d);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500484 return 0;
485}
486
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500487int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000488 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000489 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500490 return -1;
491 if (tar_extract_all(t, charRootDir) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000492 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500493 return -1;
494 }
495 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000496 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500497 return -1;
498 }
499 return 0;
500}
501
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500502int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000503 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200504
505 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500506 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000507 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000508 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500509 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000510 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600511 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000512 if (ret < 1) {
513 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
514 return -1;
515 }
516 if (ret == 1) {
517 LOGERR("Decrypted file is not in tar format.\n");
518 return -1;
519 }
520 if (ret == 3) {
521 LOGINFO("Extracting encrypted and compressed tar.\n");
522 Archive_Current_Type = 3;
523 } else
524 LOGINFO("Extracting encrypted tar.\n");
525 return extractTar();
526 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000527 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500528 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500529 }
530}
531
Dees Troye0a433a2013-12-02 04:10:37 +0000532int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 struct stat st;
534 char buf[PATH_MAX];
535 int list_size = TarList->size(), i = 0, archive_count = 0;
536 string temp;
537 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000538 char *ptr;
Dees_Troye34c1332013-02-06 19:13:00 +0000539
Dees Troye0a433a2013-12-02 04:10:37 +0000540 if (split_archives) {
541 basefn = tarfn;
542 temp = basefn + "%i%02i";
543 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
544 tarfn = actual_filename;
545 include_root_dir = true;
546 } else {
547 include_root_dir = false;
548 }
549 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 if (createTar() != 0) {
551 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
552 return -2;
553 }
554 Archive_Current_Size = 0;
555
556 while (i < list_size) {
557 if (TarList->at(i).thread_id == thread_id) {
558 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400559 lstat(buf, &st);
560 if (S_ISREG(st.st_mode)) { // item is a regular file
Dees Troyb1c6e052014-04-07 18:01:41 +0000561 if (split_archives && Archive_Current_Size + (unsigned long long)(st.st_size) > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000562 if (closeTar() != 0) {
563 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
564 return -3;
565 }
566 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000567 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000568 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000569 LOGERR("Too many archives for thread %i\n", thread_id);
570 return -4;
571 }
572 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
573 tarfn = actual_filename;
574 if (createTar() != 0) {
575 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
576 return -2;
577 }
578 Archive_Current_Size = 0;
579 }
580 Archive_Current_Size += (unsigned long long)(st.st_size);
581 }
Dees Troye0a433a2013-12-02 04:10:37 +0000582 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
583 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000584 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
585 return -1;
586 }
587 }
588 i++;
589 }
590 if (closeTar() != 0) {
591 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
592 return -3;
593 }
594 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count, i, list_size);
Dees_Troye34c1332013-02-06 19:13:00 +0000595 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500596}
597
Dees_Troy83bd4832013-05-04 12:39:56 +0000598void* twrpTar::createList(void *cookie) {
599
600 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600601 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000602 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
603 return (void*)-2;
604 }
605 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
606 return (void*)0;
607}
608
609void* twrpTar::extractMulti(void *cookie) {
610
611 twrpTar* threadTar = (twrpTar*) cookie;
612 int archive_count = 0;
613 string temp = threadTar->basefn + "%i%02i";
614 char actual_filename[255];
615 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
616 while (TWFunc::Path_Exists(actual_filename)) {
617 threadTar->tarfn = actual_filename;
618 if (threadTar->extract() != 0) {
619 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
620 return (void*)-2;
621 }
622 archive_count++;
623 if (archive_count > 99)
624 break;
625 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
626 }
627 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
628 return (void*)0;
629}
630
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500631int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
632 char* charTarFile = (char*) fn.c_str();
633
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200634 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 -0500635 return -1;
636 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200637 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 -0500638 return -1;
639 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500640 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500641 if (tar_append_file(t, file, file) == -1)
642 return -1;
643 }
644 if (tar_append_eof(t) == -1)
645 return -1;
646 if (tar_close(t) == -1)
647 return -1;
648 return 0;
649}
650
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500651int twrpTar::createTar() {
652 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000653 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000654 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500655
Dees_Troy83bd4832013-05-04 12:39:56 +0000656 if (use_encryption && use_compression) {
657 // Compressed and encrypted
658 Archive_Current_Type = 3;
659 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000660 int i, pipes[4];
661
662 if (pipe(pipes) < 0) {
663 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500664 return -1;
665 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000666 if (pipe(pipes + 2) < 0) {
667 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500668 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000669 }
Dees Troy9d723272014-04-07 17:13:10 +0000670 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);
671 if (output_fd < 0) {
672 LOGERR("Failed to open '%s'\n", tarfn.c_str());
673 for (i = 0; i < 4; i++)
674 close(pipes[i]); // close all
675 return -1;
676 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000677 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400678
Dees_Troy83bd4832013-05-04 12:39:56 +0000679 if (pigz_pid < 0) {
680 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000681 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000682 for (i = 0; i < 4; i++)
683 close(pipes[i]); // close all
684 return -1;
685 } else if (pigz_pid == 0) {
686 // pigz Child
687 close(pipes[1]);
688 close(pipes[2]);
689 close(0);
690 dup2(pipes[0], 0);
691 close(1);
692 dup2(pipes[3], 1);
693 if (execlp("pigz", "pigz", "-", NULL) < 0) {
694 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000695 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000696 close(pipes[0]);
697 close(pipes[3]);
698 _exit(-1);
699 }
700 } else {
701 // Parent
702 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400703
Dees_Troy83bd4832013-05-04 12:39:56 +0000704 if (oaes_pid < 0) {
705 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000706 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000707 for (i = 0; i < 4; i++)
708 close(pipes[i]); // close all
709 return -1;
710 } else if (oaes_pid == 0) {
711 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000712 close(pipes[0]);
713 close(pipes[1]);
714 close(pipes[3]);
715 close(0);
716 dup2(pipes[2], 0);
717 close(1);
718 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600719 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000720 LOGERR("execlp openaes ERROR!\n");
721 close(pipes[2]);
722 close(output_fd);
723 _exit(-1);
724 }
725 } else {
726 // Parent
727 close(pipes[0]);
728 close(pipes[2]);
729 close(pipes[3]);
730 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200731 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 +0000732 close(fd);
733 LOGERR("tar_fdopen failed\n");
734 return -1;
735 }
736 return 0;
737 }
738 }
739 } else if (use_compression) {
740 // Compressed
741 Archive_Current_Type = 1;
742 LOGINFO("Using compression...\n");
743 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000744 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);
745 if (output_fd < 0) {
746 LOGERR("Failed to open '%s'\n", tarfn.c_str());
747 close(pigzfd[0]);
748 return -1;
749 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000750
751 if (pipe(pigzfd) < 0) {
752 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000753 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000754 return -1;
755 }
756 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400757
Dees_Troy83bd4832013-05-04 12:39:56 +0000758 if (pigz_pid < 0) {
759 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000760 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000761 close(pigzfd[0]);
762 close(pigzfd[1]);
763 return -1;
764 } else if (pigz_pid == 0) {
765 // Child
766 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000767 dup2(pigzfd[0], 0); // remap stdin
768 dup2(output_fd, 1); // remap stdout to output file
769 if (execlp("pigz", "pigz", "-", NULL) < 0) {
770 LOGERR("execlp pigz ERROR!\n");
771 close(output_fd);
772 close(pigzfd[0]);
773 _exit(-1);
774 }
775 } else {
776 // Parent
777 close(pigzfd[0]); // close parent input
778 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200779 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 +0000780 close(fd);
781 LOGERR("tar_fdopen failed\n");
782 return -1;
783 }
784 }
785 } else if (use_encryption) {
786 // Encrypted
787 Archive_Current_Type = 2;
788 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000789 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000790 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);
791 if (output_fd < 0) {
792 LOGERR("Failed to open '%s'\n", tarfn.c_str());
793 return -1;
794 }
795 if (pipe(oaesfd) < 0) {
796 LOGERR("Error creating pipe\n");
797 close(output_fd);
798 return -1;
799 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000800 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400801
Dees_Troy83bd4832013-05-04 12:39:56 +0000802 if (oaes_pid < 0) {
803 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000804 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000805 close(oaesfd[0]);
806 close(oaesfd[1]);
807 return -1;
808 } else if (oaes_pid == 0) {
809 // Child
810 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000811 dup2(oaesfd[0], 0); // remap stdin
812 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600813 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000814 LOGERR("execlp openaes ERROR!\n");
815 close(output_fd);
816 close(oaesfd[0]);
817 _exit(-1);
818 }
819 } else {
820 // Parent
821 close(oaesfd[0]); // close parent input
822 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200823 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 +0000824 close(fd);
825 LOGERR("tar_fdopen failed\n");
826 return -1;
827 }
828 return 0;
829 }
830 } else {
831 // Not compressed or encrypted
832 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200833 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 +0000834 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
835 return -1;
836 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500837 }
838 return 0;
839}
840
Dees_Troy83bd4832013-05-04 12:39:56 +0000841int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000842 char* charRootDir = (char*) tardir.c_str();
843 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000844 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500845
Dees_Troy83bd4832013-05-04 12:39:56 +0000846 if (Archive_Current_Type == 3) {
847 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000848 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +0000849 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
850 if (input_fd < 0) {
851 LOGERR("Failed to open '%s'\n", tarfn.c_str());
852 return -1;
853 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000854
855 if (pipe(pipes) < 0) {
856 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000857 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500858 return -1;
859 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000860 if (pipe(pipes + 2) < 0) {
861 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000862 close(pipes[0]);
863 close(pipes[1]);
864 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500865 return -1;
866 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000867 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400868
Dees_Troy83bd4832013-05-04 12:39:56 +0000869 if (oaes_pid < 0) {
870 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000871 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000872 for (i = 0; i < 4; i++)
873 close(pipes[i]); // close all
874 return -1;
875 } else if (oaes_pid == 0) {
876 // openaes Child
877 close(pipes[0]); // Close pipes that are not used by this child
878 close(pipes[2]);
879 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000880 close(0);
881 dup2(input_fd, 0);
882 close(1);
883 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600884 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000885 LOGERR("execlp openaes ERROR!\n");
886 close(input_fd);
887 close(pipes[1]);
888 _exit(-1);
889 }
890 } else {
891 // Parent
892 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400893
Dees_Troy83bd4832013-05-04 12:39:56 +0000894 if (pigz_pid < 0) {
895 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000896 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000897 for (i = 0; i < 4; i++)
898 close(pipes[i]); // close all
899 return -1;
900 } else if (pigz_pid == 0) {
901 // pigz Child
902 close(pipes[1]); // Close pipes not used by this child
903 close(pipes[2]);
904 close(0);
905 dup2(pipes[0], 0);
906 close(1);
907 dup2(pipes[3], 1);
908 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
909 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000910 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000911 close(pipes[0]);
912 close(pipes[3]);
913 _exit(-1);
914 }
915 } else {
916 // Parent
917 close(pipes[0]); // Close pipes not used by parent
918 close(pipes[1]);
919 close(pipes[3]);
920 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200921 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 +0000922 close(fd);
923 LOGERR("tar_fdopen failed\n");
924 return -1;
925 }
926 }
927 }
928 } else if (Archive_Current_Type == 2) {
929 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000930 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000931 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
932 if (input_fd < 0) {
933 LOGERR("Failed to open '%s'\n", tarfn.c_str());
934 return -1;
935 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000936
Dees Troy9d723272014-04-07 17:13:10 +0000937 if (pipe(oaesfd) < 0) {
938 LOGERR("Error creating pipe\n");
939 close(input_fd);
940 return -1;
941 }
942
Dees_Troy83bd4832013-05-04 12:39:56 +0000943 oaes_pid = fork();
944 if (oaes_pid < 0) {
945 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000946 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000947 close(oaesfd[0]);
948 close(oaesfd[1]);
949 return -1;
950 } else if (oaes_pid == 0) {
951 // Child
952 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000953 close(0); // close stdin
954 dup2(oaesfd[1], 1); // remap stdout
955 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -0600956 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000957 LOGERR("execlp openaes ERROR!\n");
958 close(input_fd);
959 close(oaesfd[1]);
960 _exit(-1);
961 }
962 } else {
963 // Parent
964 close(oaesfd[1]); // close parent output
965 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200966 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 +0000967 close(fd);
968 LOGERR("tar_fdopen failed\n");
969 return -1;
970 }
971 }
972 } else if (Archive_Current_Type == 1) {
973 LOGINFO("Opening as a gzip...\n");
974 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000975 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
976 if (input_fd < 0) {
977 LOGERR("Failed to open '%s'\n", tarfn.c_str());
978 return -1;
979 }
980 if (pipe(pigzfd) < 0) {
981 LOGERR("Error creating pipe\n");
982 close(input_fd);
983 return -1;
984 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000985
986 pigz_pid = fork();
987 if (pigz_pid < 0) {
988 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000989 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000990 close(pigzfd[0]);
991 close(pigzfd[1]);
992 return -1;
993 } else if (pigz_pid == 0) {
994 // Child
995 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000996 dup2(input_fd, 0); // remap input fd to stdin
997 dup2(pigzfd[1], 1); // remap stdout
998 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
999 close(pigzfd[1]);
1000 close(input_fd);
1001 LOGERR("execlp openaes ERROR!\n");
1002 _exit(-1);
1003 }
1004 } else {
1005 // Parent
1006 close(pigzfd[1]); // close parent output
1007 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001008 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 +00001009 close(fd);
1010 LOGERR("tar_fdopen failed\n");
1011 return -1;
1012 }
1013 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001014 } 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 +00001015 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1016 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001017 }
1018 return 0;
1019}
1020
1021string twrpTar::Strip_Root_Dir(string Path) {
1022 string temp;
1023 size_t slash;
1024
1025 if (Path.substr(0, 1) == "/")
1026 temp = Path.substr(1, Path.size() - 1);
1027 else
1028 temp = Path;
1029 slash = temp.find("/");
1030 if (slash == string::npos)
1031 return temp;
1032 else {
1033 string stripped;
1034
1035 stripped = temp.substr(slash, temp.size() - slash);
1036 return stripped;
1037 }
1038 return temp;
1039}
1040
1041int twrpTar::addFile(string fn, bool include_root) {
1042 char* charTarFile = (char*) fn.c_str();
1043 if (include_root) {
1044 if (tar_append_file(t, charTarFile, NULL) == -1)
1045 return -1;
1046 } else {
1047 string temp = Strip_Root_Dir(fn);
1048 char* charTarPath = (char*) temp.c_str();
1049 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1050 return -1;
1051 }
1052 return 0;
1053}
1054
Dees_Troy83bd4832013-05-04 12:39:56 +00001055int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001056 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001057 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001058 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001059 tar_close(t);
1060 return -1;
1061 }
1062 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001063 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001064 return -1;
1065 }
Dees_Troy2727b992013-08-14 20:09:30 +00001066 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001067 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001068 int status;
1069 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1070 return -1;
1071 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1072 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001073 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001074 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001075 if (use_compression && !use_encryption) {
1076 string gzname = tarfn + ".gz";
1077 if (TWFunc::Path_Exists(gzname)) {
1078 rename(gzname.c_str(), tarfn.c_str());
1079 }
1080 }
1081 if (TWFunc::Get_File_Size(tarfn) == 0) {
1082 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1083 return -1;
1084 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001085 return 0;
1086}
1087
1088int twrpTar::removeEOT(string tarFile) {
1089 char* charTarFile = (char*) tarFile.c_str();
1090 off_t tarFileEnd;
1091 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001092 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001093 tar_skip_regfile(t);
1094 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001095 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001096 if (tar_close(t) == -1)
1097 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001098 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001099 return -1;
1100 return 0;
1101}
1102
n0d33b511632013-03-06 21:14:15 +02001103int twrpTar::entryExists(string entry) {
1104 char* searchstr = (char*)entry.c_str();
1105 int ret;
1106
Dees_Troy83bd4832013-05-04 12:39:56 +00001107 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001108
Dees_Troy83bd4832013-05-04 12:39:56 +00001109 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001110 ret = 0;
1111 else
1112 ret = tar_find(t, searchstr);
1113
Dees_Troy83bd4832013-05-04 12:39:56 +00001114 if (closeTar() != 0)
1115 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001116
1117 return ret;
1118}
1119
Dees_Troye34c1332013-02-06 19:13:00 +00001120extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1121 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001122}