blob: c024821ab34e39612aa91b15ae8d7634cbcfbbb3 [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_Troy83bd4832013-05-04 12:39:56 +000070void twrpTar::setexcl(string exclude) {
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -040071 tarexclude.push_back(exclude);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050072}
73
Dees Troye0a433a2013-12-02 04:10:37 +000074void twrpTar::setsize(unsigned long long backup_size) {
75 Total_Backup_Size = backup_size;
76}
77
Ethan Yonker87af5632014-02-10 11:56:35 -060078void twrpTar::setpassword(string pass) {
79 password = pass;
80}
81
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050082int twrpTar::createTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +000083 int status = 0;
84 pid_t pid, rc_pid;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050085 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000086 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050087 return -1;
88 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050089 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +000090 // Child process
91 if (use_encryption || userdata_encryption) {
92 LOGINFO("Using encryption\n");
93 DIR* d;
94 struct dirent* de;
95 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1;
96 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
97 int item_len, ret, thread_error = 0;
98 std::vector<TarListStruct> RegularList;
99 std::vector<TarListStruct> EncryptList;
100 string FileName;
101 struct TarListStruct TarItem;
102 twrpTar reg, enc[9];
103 struct stat st;
104 pthread_t enc_thread[9];
105 pthread_attr_t tattr;
106 void *thread_return;
107
108 core_count = sysconf(_SC_NPROCESSORS_CONF);
109 if (core_count > 8)
110 core_count = 8;
111 LOGINFO(" Core Count : %llu\n", core_count);
112 Archive_Current_Size = 0;
113
114 d = opendir(tardir.c_str());
115 if (d == NULL) {
116 LOGERR("error opening '%s'\n", tardir.c_str());
117 _exit(-1);
118 }
119 // Figure out the size of all data to be encrypted and create a list of unencrypted files
120 while ((de = readdir(d)) != NULL) {
121 FileName = tardir + "/";
122 FileName += de->d_name;
123 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
124 continue; // Skip /data/media
125 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
126 continue;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100127 if (de->d_type == DT_DIR && !du.check_skip_dirs(tardir, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000128 item_len = strlen(de->d_name);
129 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
130 if (Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id) < 0) {
131 LOGERR("Error in Generate_TarList with regular list!\n");
132 closedir(d);
133 _exit(-1);
134 }
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500135 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000136 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500137 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000138 }
139 } else if (de->d_type == DT_REG) {
140 stat(FileName.c_str(), &st);
141 encrypt_size += (unsigned long long)(st.st_size);
142 }
143 }
144 closedir(d);
145
146 target_size = encrypt_size / core_count;
147 target_size++;
148 LOGINFO(" Unencrypted size: %llu\n", regular_size);
149 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
150 LOGINFO(" Target size : %llu\n", target_size);
151 if (!userdata_encryption) {
152 enc_thread_id = 0;
153 start_thread_id = 0;
154 core_count--;
155 }
156 Archive_Current_Size = 0;
157
158 d = opendir(tardir.c_str());
159 if (d == NULL) {
160 LOGERR("error opening '%s'\n", tardir.c_str());
161 _exit(-1);
162 }
163 // Divide up the encrypted file list for threading
164 while ((de = readdir(d)) != NULL) {
165 FileName = tardir + "/";
166 FileName += de->d_name;
167 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
168 continue; // Skip /data/media
169 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
170 continue;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100171 if (de->d_type == DT_DIR && !du.check_skip_dirs(tardir, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000172 item_len = strlen(de->d_name);
173 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
174 // Do nothing, we added these to RegularList earlier
175 } else {
176 FileName = tardir + "/";
177 FileName += de->d_name;
178 if (Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id) < 0) {
179 LOGERR("Error in Generate_TarList with encrypted list!\n");
180 closedir(d);
181 _exit(-1);
182 }
183 }
184 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
185 stat(FileName.c_str(), &st);
186 if (de->d_type == DT_REG)
187 Archive_Current_Size += (unsigned long long)(st.st_size);
188 TarItem.fn = FileName;
189 TarItem.thread_id = enc_thread_id;
190 EncryptList.push_back(TarItem);
191 }
192 }
193 closedir(d);
194 if (enc_thread_id != core_count) {
195 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
196 if (enc_thread_id > core_count)
197 _exit(-1);
198 else
199 LOGERR("Continuining anyway.");
200 }
201
202 if (userdata_encryption) {
203 // Create a backup of unencrypted data
204 reg.setfn(tarfn);
205 reg.ItemList = &RegularList;
206 reg.thread_id = 0;
207 reg.use_encryption = 0;
208 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000209 reg.split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000210 LOGINFO("Creating unencrypted backup...\n");
211 if (createList((void*)&reg) != 0) {
212 LOGERR("Error creating unencrypted backup.\n");
213 _exit(-1);
214 }
215 }
216
217 if (pthread_attr_init(&tattr)) {
218 LOGERR("Unable to pthread_attr_init\n");
219 _exit(-1);
220 }
221 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
222 LOGERR("Error setting pthread_attr_setdetachstate\n");
223 _exit(-1);
224 }
225 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
226 LOGERR("Error setting pthread_attr_setscope\n");
227 _exit(-1);
228 }
229 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
230 LOGERR("Error setting pthread_attr_setstacksize\n");
231 _exit(-1);
232 }*/
233
234 // Create threads for the divided up encryption lists
235 for (i = start_thread_id; i <= core_count; i++) {
236 enc[i].setdir(tardir);
237 enc[i].setfn(tarfn);
238 enc[i].ItemList = &EncryptList;
239 enc[i].thread_id = i;
240 enc[i].use_encryption = use_encryption;
241 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000242 enc[i].split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 LOGINFO("Start encryption thread %i\n", i);
244 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
245 if (ret) {
246 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).", i, ret);
247 if (createList((void*)&enc[i]) != 0) {
248 LOGERR("Error creating encrypted backup %i.\n", i);
249 _exit(-1);
250 } else {
251 enc[i].thread_id = i + 1;
252 }
253 }
254 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
255 }
256 if (pthread_attr_destroy(&tattr)) {
257 LOGERR("Failed to pthread_attr_destroy\n");
258 }
259 for (i = start_thread_id; i <= core_count; i++) {
260 if (enc[i].thread_id == i) {
261 if (pthread_join(enc_thread[i], &thread_return)) {
262 LOGERR("Error joining thread %i\n", i);
263 _exit(-1);
264 } else {
265 LOGINFO("Joined thread %i.\n", i);
266 ret = (int)thread_return;
267 if (ret != 0) {
268 thread_error = 1;
269 LOGERR("Thread %i returned an error %i.\n", i, ret);
270 _exit(-1);
271 }
272 }
273 } else {
274 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
275 }
276 }
277 if (thread_error) {
278 LOGERR("Error returned by one or more threads.\n");
279 _exit(-1);
280 }
281 LOGINFO("Finished encrypted backup.\n");
282 _exit(0);
283 } else {
Dees Troye0a433a2013-12-02 04:10:37 +0000284 std::vector<TarListStruct> FileList;
285 unsigned thread_id = 0;
286 unsigned long long target_size = 0;
287 twrpTar reg;
288
289 // Generate list of files to back up
290 if (Generate_TarList(tardir, &FileList, &target_size, &thread_id) < 0) {
291 LOGERR("Error in Generate_TarList!\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000292 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000293 }
294 // Create a backup
295 reg.setfn(tarfn);
296 reg.ItemList = &FileList;
297 reg.thread_id = 0;
298 reg.use_encryption = 0;
299 reg.use_compression = use_compression;
300 reg.setsize(Total_Backup_Size);
301 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
302 gui_print("Breaking backup file into multiple archives...\n");
303 reg.split_archives = 1;
304 } else {
305 reg.split_archives = 0;
306 }
307 LOGINFO("Creating backup...\n");
308 if (createList((void*)&reg) != 0) {
309 LOGERR("Error creating backup.\n");
310 _exit(-1);
311 }
312 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000313 }
314 } else {
315 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500316 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500317 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500318 return 0;
319}
320
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500321int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000322 int status = 0;
323 pid_t pid, rc_pid;
324
325 pid = fork();
326 if (pid >= 0) // fork was successful
327 {
328 if (pid == 0) // child process
329 {
330 if (TWFunc::Path_Exists(tarfn)) {
331 LOGINFO("Single archive\n");
332 if (extract() != 0)
333 _exit(-1);
334 else
335 _exit(0);
336 } else {
337 LOGINFO("Multiple archives\n");
338 string temp;
339 char actual_filename[255];
340 twrpTar tars[9];
341 pthread_t tar_thread[9];
342 pthread_attr_t tattr;
343 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
344 void *thread_return;
345
346 basefn = tarfn;
347 temp = basefn + "%i%02i";
348 tarfn += "000";
349 if (!TWFunc::Path_Exists(tarfn)) {
350 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
351 _exit(-1);
352 }
353 if (TWFunc::Get_File_Type(tarfn) != 2) {
354 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
355 tars[0].basefn = basefn;
356 tars[0].thread_id = 0;
357 if (extractMulti((void*)&tars[0]) != 0) {
358 LOGERR("Error extracting split archive.\n");
359 _exit(-1);
360 }
361 } else {
362 start_thread_id = 0;
363 }
364 // Start threading encrypted restores
365 if (pthread_attr_init(&tattr)) {
366 LOGERR("Unable to pthread_attr_init\n");
367 _exit(-1);
368 }
369 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
370 LOGERR("Error setting pthread_attr_setdetachstate\n");
371 _exit(-1);
372 }
373 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
374 LOGERR("Error setting pthread_attr_setscope\n");
375 _exit(-1);
376 }
377 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
378 LOGERR("Error setting pthread_attr_setstacksize\n");
379 _exit(-1);
380 }*/
381 for (i = start_thread_id; i < 9; i++) {
382 sprintf(actual_filename, temp.c_str(), i, 0);
383 if (TWFunc::Path_Exists(actual_filename)) {
384 thread_count++;
385 tars[i].basefn = basefn;
386 tars[i].thread_id = i;
387 LOGINFO("Creating extract thread ID %i\n", i);
388 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
389 if (ret) {
390 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).", i, ret);
391 if (extractMulti((void*)&tars[i]) != 0) {
392 LOGERR("Error extracting backup in thread %i.\n", i);
393 _exit(-1);
394 } else {
395 tars[i].thread_id = i + 1;
396 }
397 }
398 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
399 } else {
400 break;
401 }
402 }
403 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
404 if (tars[i].thread_id == i) {
405 if (pthread_join(tar_thread[i], &thread_return)) {
406 LOGERR("Error joining thread %i\n", i);
407 _exit(-1);
408 } else {
409 LOGINFO("Joined thread %i.\n", i);
410 ret = (int)thread_return;
411 if (ret != 0) {
412 thread_error = 1;
413 LOGERR("Thread %i returned an error %i.\n", i, ret);
414 _exit(-1);
415 }
416 }
417 } else {
418 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
419 }
420 }
421 if (thread_error) {
422 LOGERR("Error returned by one or more threads.\n");
423 _exit(-1);
424 }
425 LOGINFO("Finished encrypted backup.\n");
426 _exit(0);
427 }
428 }
429 else // parent process
430 {
431 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
432 return -1;
433 }
434 }
435 else // fork has failed
436 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000437 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500438 return -1;
439 }
440 return 0;
441}
442
Dees_Troy83bd4832013-05-04 12:39:56 +0000443int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
444 DIR* d;
445 struct dirent* de;
446 struct stat st;
447 string FileName;
448 struct TarListStruct TarItem;
449 string::size_type i;
450 bool skip;
451
452 if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
453 return 0; // Skip /data/media
454
455 d = opendir(Path.c_str());
456 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000457 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000458 closedir(d);
459 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500460 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000461 while ((de = readdir(d)) != NULL) {
462 // Skip excluded stuff
Dees Troye0a433a2013-12-02 04:10:37 +0000463 FileName = Path + "/";
464 FileName += de->d_name;
465 if (tarexclude.size() > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000466 skip = false;
Dees Troye0a433a2013-12-02 04:10:37 +0000467 for (i = 0; i < tarexclude.size(); i++) {
468 if (FileName == tarexclude[i]) {
469 LOGINFO("Excluding %s\n", FileName.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000470 break;
471 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500472 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000473 if (skip)
474 continue;
475 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000476 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
477 continue; // Skip /data/media
478 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
479 continue;
480 TarItem.fn = FileName;
481 TarItem.thread_id = *thread_id;
Vojtech Bocek05f87d62014-03-11 22:08:23 +0100482 if (de->d_type == DT_DIR && !du.check_skip_dirs(Path, de->d_name)) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000483 TarList->push_back(TarItem);
484 if (Generate_TarList(FileName, TarList, Target_Size, thread_id) < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500485 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000486 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
487 stat(FileName.c_str(), &st);
488 TarList->push_back(TarItem);
489 if (de->d_type == DT_REG)
490 Archive_Current_Size += st.st_size;
491 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
492 *thread_id = *thread_id + 1;
493 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500494 }
495 }
496 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000497 closedir(d);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500498 return 0;
499}
500
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500501int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000502 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000503 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500504 return -1;
505 if (tar_extract_all(t, charRootDir) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000506 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500507 return -1;
508 }
509 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000510 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500511 return -1;
512 }
513 return 0;
514}
515
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500516int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000517 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200518
519 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500520 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000521 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000522 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500523 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000524 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600525 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000526 if (ret < 1) {
527 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
528 return -1;
529 }
530 if (ret == 1) {
531 LOGERR("Decrypted file is not in tar format.\n");
532 return -1;
533 }
534 if (ret == 3) {
535 LOGINFO("Extracting encrypted and compressed tar.\n");
536 Archive_Current_Type = 3;
537 } else
538 LOGINFO("Extracting encrypted tar.\n");
539 return extractTar();
540 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000541 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500542 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500543 }
544}
545
Dees Troye0a433a2013-12-02 04:10:37 +0000546int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000547 struct stat st;
548 char buf[PATH_MAX];
549 int list_size = TarList->size(), i = 0, archive_count = 0;
550 string temp;
551 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000552 char *ptr;
Dees_Troye34c1332013-02-06 19:13:00 +0000553
Dees Troye0a433a2013-12-02 04:10:37 +0000554 if (split_archives) {
555 basefn = tarfn;
556 temp = basefn + "%i%02i";
557 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
558 tarfn = actual_filename;
559 include_root_dir = true;
560 } else {
561 include_root_dir = false;
562 }
563 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000564 if (createTar() != 0) {
565 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
566 return -2;
567 }
568 Archive_Current_Size = 0;
569
570 while (i < list_size) {
571 if (TarList->at(i).thread_id == thread_id) {
572 strcpy(buf, TarList->at(i).fn.c_str());
573 stat(buf, &st);
574 if (st.st_mode & S_IFREG) { // item is a regular file
575 if (Archive_Current_Size + (unsigned long long)(st.st_size) > MAX_ARCHIVE_SIZE) {
576 if (closeTar() != 0) {
577 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
578 return -3;
579 }
580 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000581 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000582 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000583 LOGERR("Too many archives for thread %i\n", thread_id);
584 return -4;
585 }
586 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
587 tarfn = actual_filename;
588 if (createTar() != 0) {
589 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
590 return -2;
591 }
592 Archive_Current_Size = 0;
593 }
594 Archive_Current_Size += (unsigned long long)(st.st_size);
595 }
Dees Troye0a433a2013-12-02 04:10:37 +0000596 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
597 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000598 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
599 return -1;
600 }
601 }
602 i++;
603 }
604 if (closeTar() != 0) {
605 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
606 return -3;
607 }
608 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count, i, list_size);
Dees_Troye34c1332013-02-06 19:13:00 +0000609 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500610}
611
Dees_Troy83bd4832013-05-04 12:39:56 +0000612void* twrpTar::createList(void *cookie) {
613
614 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600615 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000616 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
617 return (void*)-2;
618 }
619 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
620 return (void*)0;
621}
622
623void* twrpTar::extractMulti(void *cookie) {
624
625 twrpTar* threadTar = (twrpTar*) cookie;
626 int archive_count = 0;
627 string temp = threadTar->basefn + "%i%02i";
628 char actual_filename[255];
629 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
630 while (TWFunc::Path_Exists(actual_filename)) {
631 threadTar->tarfn = actual_filename;
632 if (threadTar->extract() != 0) {
633 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
634 return (void*)-2;
635 }
636 archive_count++;
637 if (archive_count > 99)
638 break;
639 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
640 }
641 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
642 return (void*)0;
643}
644
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500645int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
646 char* charTarFile = (char*) fn.c_str();
647
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200648 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 -0500649 return -1;
650 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200651 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 -0500652 return -1;
653 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500654 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500655 if (tar_append_file(t, file, file) == -1)
656 return -1;
657 }
658 if (tar_append_eof(t) == -1)
659 return -1;
660 if (tar_close(t) == -1)
661 return -1;
662 return 0;
663}
664
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500665int twrpTar::createTar() {
666 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000667 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000668 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500669
Dees_Troy83bd4832013-05-04 12:39:56 +0000670 if (use_encryption && use_compression) {
671 // Compressed and encrypted
672 Archive_Current_Type = 3;
673 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000674 int i, pipes[4];
675
676 if (pipe(pipes) < 0) {
677 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500678 return -1;
679 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000680 if (pipe(pipes + 2) < 0) {
681 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500682 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000683 }
684 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400685
Dees_Troy83bd4832013-05-04 12:39:56 +0000686 if (pigz_pid < 0) {
687 LOGERR("pigz fork() failed\n");
688 for (i = 0; i < 4; i++)
689 close(pipes[i]); // close all
690 return -1;
691 } else if (pigz_pid == 0) {
692 // pigz Child
693 close(pipes[1]);
694 close(pipes[2]);
695 close(0);
696 dup2(pipes[0], 0);
697 close(1);
698 dup2(pipes[3], 1);
699 if (execlp("pigz", "pigz", "-", NULL) < 0) {
700 LOGERR("execlp pigz ERROR!\n");
701 close(pipes[0]);
702 close(pipes[3]);
703 _exit(-1);
704 }
705 } else {
706 // Parent
707 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400708
Dees_Troy83bd4832013-05-04 12:39:56 +0000709 if (oaes_pid < 0) {
710 LOGERR("openaes fork() failed\n");
711 for (i = 0; i < 4; i++)
712 close(pipes[i]); // close all
713 return -1;
714 } else if (oaes_pid == 0) {
715 // openaes Child
Dees_Troy5612cc82013-07-24 19:45:58 +0000716 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);
Dees_Troy83bd4832013-05-04 12:39:56 +0000717 if (output_fd < 0) {
718 LOGERR("Failed to open '%s'\n", tarfn.c_str());
719 for (i = 0; i < 4; i++)
720 close(pipes[i]); // close all
721 return -1;
722 }
723 close(pipes[0]);
724 close(pipes[1]);
725 close(pipes[3]);
726 close(0);
727 dup2(pipes[2], 0);
728 close(1);
729 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600730 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000731 LOGERR("execlp openaes ERROR!\n");
732 close(pipes[2]);
733 close(output_fd);
734 _exit(-1);
735 }
736 } else {
737 // Parent
738 close(pipes[0]);
739 close(pipes[2]);
740 close(pipes[3]);
741 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200742 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 +0000743 close(fd);
744 LOGERR("tar_fdopen failed\n");
745 return -1;
746 }
747 return 0;
748 }
749 }
750 } else if (use_compression) {
751 // Compressed
752 Archive_Current_Type = 1;
753 LOGINFO("Using compression...\n");
754 int pigzfd[2];
755
756 if (pipe(pigzfd) < 0) {
757 LOGERR("Error creating pipe\n");
758 return -1;
759 }
760 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400761
Dees_Troy83bd4832013-05-04 12:39:56 +0000762 if (pigz_pid < 0) {
763 LOGERR("fork() failed\n");
764 close(pigzfd[0]);
765 close(pigzfd[1]);
766 return -1;
767 } else if (pigz_pid == 0) {
768 // Child
769 close(pigzfd[1]); // close unused output pipe
Dees_Troy5612cc82013-07-24 19:45:58 +0000770 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);
Dees_Troy83bd4832013-05-04 12:39:56 +0000771 if (output_fd < 0) {
772 LOGERR("Failed to open '%s'\n", tarfn.c_str());
773 close(pigzfd[0]);
774 _exit(-1);
775 }
776 dup2(pigzfd[0], 0); // remap stdin
777 dup2(output_fd, 1); // remap stdout to output file
778 if (execlp("pigz", "pigz", "-", NULL) < 0) {
779 LOGERR("execlp pigz ERROR!\n");
780 close(output_fd);
781 close(pigzfd[0]);
782 _exit(-1);
783 }
784 } else {
785 // Parent
786 close(pigzfd[0]); // close parent input
787 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200788 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 +0000789 close(fd);
790 LOGERR("tar_fdopen failed\n");
791 return -1;
792 }
793 }
794 } else if (use_encryption) {
795 // Encrypted
796 Archive_Current_Type = 2;
797 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000798 int oaesfd[2];
799 pipe(oaesfd);
800 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");
804 close(oaesfd[0]);
805 close(oaesfd[1]);
806 return -1;
807 } else if (oaes_pid == 0) {
808 // Child
809 close(oaesfd[1]); // close unused
Dees_Troy5612cc82013-07-24 19:45:58 +0000810 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);
Dees_Troy83bd4832013-05-04 12:39:56 +0000811 if (output_fd < 0) {
812 LOGERR("Failed to open '%s'\n", tarfn.c_str());
813 _exit(-1);
814 }
815 dup2(oaesfd[0], 0); // remap stdin
816 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600817 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000818 LOGERR("execlp openaes ERROR!\n");
819 close(output_fd);
820 close(oaesfd[0]);
821 _exit(-1);
822 }
823 } else {
824 // Parent
825 close(oaesfd[0]); // close parent input
826 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200827 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 +0000828 close(fd);
829 LOGERR("tar_fdopen failed\n");
830 return -1;
831 }
832 return 0;
833 }
834 } else {
835 // Not compressed or encrypted
836 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200837 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 +0000838 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
839 return -1;
840 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500841 }
842 return 0;
843}
844
Dees_Troy83bd4832013-05-04 12:39:56 +0000845int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000846 char* charRootDir = (char*) tardir.c_str();
847 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000848 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500849
Dees_Troy83bd4832013-05-04 12:39:56 +0000850 if (Archive_Current_Type == 3) {
851 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000852 int i, pipes[4];
853
854 if (pipe(pipes) < 0) {
855 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500856 return -1;
857 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000858 if (pipe(pipes + 2) < 0) {
859 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500860 return -1;
861 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000862 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400863
Dees_Troy83bd4832013-05-04 12:39:56 +0000864 if (oaes_pid < 0) {
865 LOGERR("pigz fork() failed\n");
866 for (i = 0; i < 4; i++)
867 close(pipes[i]); // close all
868 return -1;
869 } else if (oaes_pid == 0) {
870 // openaes Child
871 close(pipes[0]); // Close pipes that are not used by this child
872 close(pipes[2]);
873 close(pipes[3]);
874 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
875 if (input_fd < 0) {
876 LOGERR("Failed to open '%s'\n", tarfn.c_str());
877 close(pipes[1]);
878 _exit(-1);
879 }
880 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");
896 for (i = 0; i < 4; i++)
897 close(pipes[i]); // close all
898 return -1;
899 } else if (pigz_pid == 0) {
900 // pigz Child
901 close(pipes[1]); // Close pipes not used by this child
902 close(pipes[2]);
903 close(0);
904 dup2(pipes[0], 0);
905 close(1);
906 dup2(pipes[3], 1);
907 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
908 LOGERR("execlp pigz ERROR!\n");
909 close(pipes[0]);
910 close(pipes[3]);
911 _exit(-1);
912 }
913 } else {
914 // Parent
915 close(pipes[0]); // Close pipes not used by parent
916 close(pipes[1]);
917 close(pipes[3]);
918 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200919 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 +0000920 close(fd);
921 LOGERR("tar_fdopen failed\n");
922 return -1;
923 }
924 }
925 }
926 } else if (Archive_Current_Type == 2) {
927 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000928 int oaesfd[2];
929
930 pipe(oaesfd);
931 oaes_pid = fork();
932 if (oaes_pid < 0) {
933 LOGERR("fork() failed\n");
934 close(oaesfd[0]);
935 close(oaesfd[1]);
936 return -1;
937 } else if (oaes_pid == 0) {
938 // Child
939 close(oaesfd[0]); // Close unused pipe
940 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
941 if (input_fd < 0) {
942 LOGERR("Failed to open '%s'\n", tarfn.c_str());
943 close(oaesfd[1]);
944 _exit(-1);
945 }
946 close(0); // close stdin
947 dup2(oaesfd[1], 1); // remap stdout
948 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -0600949 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000950 LOGERR("execlp openaes ERROR!\n");
951 close(input_fd);
952 close(oaesfd[1]);
953 _exit(-1);
954 }
955 } else {
956 // Parent
957 close(oaesfd[1]); // close parent output
958 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200959 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 +0000960 close(fd);
961 LOGERR("tar_fdopen failed\n");
962 return -1;
963 }
964 }
965 } else if (Archive_Current_Type == 1) {
966 LOGINFO("Opening as a gzip...\n");
967 int pigzfd[2];
968 pipe(pigzfd);
969
970 pigz_pid = fork();
971 if (pigz_pid < 0) {
972 LOGERR("fork() failed\n");
973 close(pigzfd[0]);
974 close(pigzfd[1]);
975 return -1;
976 } else if (pigz_pid == 0) {
977 // Child
978 close(pigzfd[0]);
979 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
980 if (input_fd < 0) {
981 LOGERR("Failed to open '%s'\n", tarfn.c_str());
982 _exit(-1);
983 }
984 dup2(input_fd, 0); // remap input fd to stdin
985 dup2(pigzfd[1], 1); // remap stdout
986 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
987 close(pigzfd[1]);
988 close(input_fd);
989 LOGERR("execlp openaes ERROR!\n");
990 _exit(-1);
991 }
992 } else {
993 // Parent
994 close(pigzfd[1]); // close parent output
995 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200996 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 +0000997 close(fd);
998 LOGERR("tar_fdopen failed\n");
999 return -1;
1000 }
1001 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001002 } 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 +00001003 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1004 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001005 }
1006 return 0;
1007}
1008
1009string twrpTar::Strip_Root_Dir(string Path) {
1010 string temp;
1011 size_t slash;
1012
1013 if (Path.substr(0, 1) == "/")
1014 temp = Path.substr(1, Path.size() - 1);
1015 else
1016 temp = Path;
1017 slash = temp.find("/");
1018 if (slash == string::npos)
1019 return temp;
1020 else {
1021 string stripped;
1022
1023 stripped = temp.substr(slash, temp.size() - slash);
1024 return stripped;
1025 }
1026 return temp;
1027}
1028
1029int twrpTar::addFile(string fn, bool include_root) {
1030 char* charTarFile = (char*) fn.c_str();
1031 if (include_root) {
1032 if (tar_append_file(t, charTarFile, NULL) == -1)
1033 return -1;
1034 } else {
1035 string temp = Strip_Root_Dir(fn);
1036 char* charTarPath = (char*) temp.c_str();
1037 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1038 return -1;
1039 }
1040 return 0;
1041}
1042
Dees_Troy83bd4832013-05-04 12:39:56 +00001043int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001044 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001045 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001046 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001047 tar_close(t);
1048 return -1;
1049 }
1050 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001051 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001052 return -1;
1053 }
Dees_Troy2727b992013-08-14 20:09:30 +00001054 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001055 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001056 int status;
1057 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1058 return -1;
1059 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1060 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001061 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001062 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001063 if (use_compression && !use_encryption) {
1064 string gzname = tarfn + ".gz";
1065 if (TWFunc::Path_Exists(gzname)) {
1066 rename(gzname.c_str(), tarfn.c_str());
1067 }
1068 }
1069 if (TWFunc::Get_File_Size(tarfn) == 0) {
1070 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1071 return -1;
1072 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001073 return 0;
1074}
1075
1076int twrpTar::removeEOT(string tarFile) {
1077 char* charTarFile = (char*) tarFile.c_str();
1078 off_t tarFileEnd;
1079 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001080 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001081 tar_skip_regfile(t);
1082 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001083 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001084 if (tar_close(t) == -1)
1085 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001086 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001087 return -1;
1088 return 0;
1089}
1090
n0d33b511632013-03-06 21:14:15 +02001091int twrpTar::entryExists(string entry) {
1092 char* searchstr = (char*)entry.c_str();
1093 int ret;
1094
Dees_Troy83bd4832013-05-04 12:39:56 +00001095 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001096
Dees_Troy83bd4832013-05-04 12:39:56 +00001097 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001098 ret = 0;
1099 else
1100 ret = tar_find(t, searchstr);
1101
Dees_Troy83bd4832013-05-04 12:39:56 +00001102 if (closeTar() != 0)
1103 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001104
1105 return ret;
1106}
1107
Dees_Troye34c1332013-02-06 19:13:00 +00001108extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1109 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001110}