blob: a31fe12211cc0f4f41b381ae17bf699c3045f1cf [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;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500127 bool skip_dir = false;
128 string dir(de->d_name);
129 skip_dir = du.check_skip_dirs(dir);
130 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000131 item_len = strlen(de->d_name);
132 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
133 if (Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id) < 0) {
134 LOGERR("Error in Generate_TarList with regular list!\n");
135 closedir(d);
136 _exit(-1);
137 }
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500138 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000139 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500140 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000141 }
142 } else if (de->d_type == DT_REG) {
143 stat(FileName.c_str(), &st);
144 encrypt_size += (unsigned long long)(st.st_size);
145 }
146 }
147 closedir(d);
148
149 target_size = encrypt_size / core_count;
150 target_size++;
151 LOGINFO(" Unencrypted size: %llu\n", regular_size);
152 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
153 LOGINFO(" Target size : %llu\n", target_size);
154 if (!userdata_encryption) {
155 enc_thread_id = 0;
156 start_thread_id = 0;
157 core_count--;
158 }
159 Archive_Current_Size = 0;
160
161 d = opendir(tardir.c_str());
162 if (d == NULL) {
163 LOGERR("error opening '%s'\n", tardir.c_str());
164 _exit(-1);
165 }
166 // Divide up the encrypted file list for threading
167 while ((de = readdir(d)) != NULL) {
168 FileName = tardir + "/";
169 FileName += de->d_name;
170 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
171 continue; // Skip /data/media
172 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
173 continue;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500174 bool skip_dir = false;
175 string dir(de->d_name);
176 skip_dir = du.check_skip_dirs(dir);
177 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000178 item_len = strlen(de->d_name);
179 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
180 // Do nothing, we added these to RegularList earlier
181 } else {
182 FileName = tardir + "/";
183 FileName += de->d_name;
184 if (Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id) < 0) {
185 LOGERR("Error in Generate_TarList with encrypted list!\n");
186 closedir(d);
187 _exit(-1);
188 }
189 }
190 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
191 stat(FileName.c_str(), &st);
192 if (de->d_type == DT_REG)
193 Archive_Current_Size += (unsigned long long)(st.st_size);
194 TarItem.fn = FileName;
195 TarItem.thread_id = enc_thread_id;
196 EncryptList.push_back(TarItem);
197 }
198 }
199 closedir(d);
200 if (enc_thread_id != core_count) {
201 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
202 if (enc_thread_id > core_count)
203 _exit(-1);
204 else
205 LOGERR("Continuining anyway.");
206 }
207
208 if (userdata_encryption) {
209 // Create a backup of unencrypted data
210 reg.setfn(tarfn);
211 reg.ItemList = &RegularList;
212 reg.thread_id = 0;
213 reg.use_encryption = 0;
214 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000215 reg.split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000216 LOGINFO("Creating unencrypted backup...\n");
217 if (createList((void*)&reg) != 0) {
218 LOGERR("Error creating unencrypted backup.\n");
219 _exit(-1);
220 }
221 }
222
223 if (pthread_attr_init(&tattr)) {
224 LOGERR("Unable to pthread_attr_init\n");
225 _exit(-1);
226 }
227 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
228 LOGERR("Error setting pthread_attr_setdetachstate\n");
229 _exit(-1);
230 }
231 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
232 LOGERR("Error setting pthread_attr_setscope\n");
233 _exit(-1);
234 }
235 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
236 LOGERR("Error setting pthread_attr_setstacksize\n");
237 _exit(-1);
238 }*/
239
240 // Create threads for the divided up encryption lists
241 for (i = start_thread_id; i <= core_count; i++) {
242 enc[i].setdir(tardir);
243 enc[i].setfn(tarfn);
244 enc[i].ItemList = &EncryptList;
245 enc[i].thread_id = i;
246 enc[i].use_encryption = use_encryption;
247 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000248 enc[i].split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000249 LOGINFO("Start encryption thread %i\n", i);
250 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
251 if (ret) {
252 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).", i, ret);
253 if (createList((void*)&enc[i]) != 0) {
254 LOGERR("Error creating encrypted backup %i.\n", i);
255 _exit(-1);
256 } else {
257 enc[i].thread_id = i + 1;
258 }
259 }
260 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
261 }
262 if (pthread_attr_destroy(&tattr)) {
263 LOGERR("Failed to pthread_attr_destroy\n");
264 }
265 for (i = start_thread_id; i <= core_count; i++) {
266 if (enc[i].thread_id == i) {
267 if (pthread_join(enc_thread[i], &thread_return)) {
268 LOGERR("Error joining thread %i\n", i);
269 _exit(-1);
270 } else {
271 LOGINFO("Joined thread %i.\n", i);
272 ret = (int)thread_return;
273 if (ret != 0) {
274 thread_error = 1;
275 LOGERR("Thread %i returned an error %i.\n", i, ret);
276 _exit(-1);
277 }
278 }
279 } else {
280 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
281 }
282 }
283 if (thread_error) {
284 LOGERR("Error returned by one or more threads.\n");
285 _exit(-1);
286 }
287 LOGINFO("Finished encrypted backup.\n");
288 _exit(0);
289 } else {
Dees Troye0a433a2013-12-02 04:10:37 +0000290 std::vector<TarListStruct> FileList;
291 unsigned thread_id = 0;
292 unsigned long long target_size = 0;
293 twrpTar reg;
294
295 // Generate list of files to back up
296 if (Generate_TarList(tardir, &FileList, &target_size, &thread_id) < 0) {
297 LOGERR("Error in Generate_TarList!\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000298 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000299 }
300 // Create a backup
301 reg.setfn(tarfn);
302 reg.ItemList = &FileList;
303 reg.thread_id = 0;
304 reg.use_encryption = 0;
305 reg.use_compression = use_compression;
306 reg.setsize(Total_Backup_Size);
307 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
308 gui_print("Breaking backup file into multiple archives...\n");
309 reg.split_archives = 1;
310 } else {
311 reg.split_archives = 0;
312 }
313 LOGINFO("Creating backup...\n");
314 if (createList((void*)&reg) != 0) {
315 LOGERR("Error creating backup.\n");
316 _exit(-1);
317 }
318 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 }
320 } else {
321 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500322 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500323 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500324 return 0;
325}
326
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500327int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000328 int status = 0;
329 pid_t pid, rc_pid;
330
331 pid = fork();
332 if (pid >= 0) // fork was successful
333 {
334 if (pid == 0) // child process
335 {
336 if (TWFunc::Path_Exists(tarfn)) {
337 LOGINFO("Single archive\n");
338 if (extract() != 0)
339 _exit(-1);
340 else
341 _exit(0);
342 } else {
343 LOGINFO("Multiple archives\n");
344 string temp;
345 char actual_filename[255];
346 twrpTar tars[9];
347 pthread_t tar_thread[9];
348 pthread_attr_t tattr;
349 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
350 void *thread_return;
351
352 basefn = tarfn;
353 temp = basefn + "%i%02i";
354 tarfn += "000";
355 if (!TWFunc::Path_Exists(tarfn)) {
356 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
357 _exit(-1);
358 }
359 if (TWFunc::Get_File_Type(tarfn) != 2) {
360 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
361 tars[0].basefn = basefn;
362 tars[0].thread_id = 0;
363 if (extractMulti((void*)&tars[0]) != 0) {
364 LOGERR("Error extracting split archive.\n");
365 _exit(-1);
366 }
367 } else {
368 start_thread_id = 0;
369 }
370 // Start threading encrypted restores
371 if (pthread_attr_init(&tattr)) {
372 LOGERR("Unable to pthread_attr_init\n");
373 _exit(-1);
374 }
375 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
376 LOGERR("Error setting pthread_attr_setdetachstate\n");
377 _exit(-1);
378 }
379 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
380 LOGERR("Error setting pthread_attr_setscope\n");
381 _exit(-1);
382 }
383 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
384 LOGERR("Error setting pthread_attr_setstacksize\n");
385 _exit(-1);
386 }*/
387 for (i = start_thread_id; i < 9; i++) {
388 sprintf(actual_filename, temp.c_str(), i, 0);
389 if (TWFunc::Path_Exists(actual_filename)) {
390 thread_count++;
391 tars[i].basefn = basefn;
392 tars[i].thread_id = i;
393 LOGINFO("Creating extract thread ID %i\n", i);
394 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
395 if (ret) {
396 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).", i, ret);
397 if (extractMulti((void*)&tars[i]) != 0) {
398 LOGERR("Error extracting backup in thread %i.\n", i);
399 _exit(-1);
400 } else {
401 tars[i].thread_id = i + 1;
402 }
403 }
404 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
405 } else {
406 break;
407 }
408 }
409 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
410 if (tars[i].thread_id == i) {
411 if (pthread_join(tar_thread[i], &thread_return)) {
412 LOGERR("Error joining thread %i\n", i);
413 _exit(-1);
414 } else {
415 LOGINFO("Joined thread %i.\n", i);
416 ret = (int)thread_return;
417 if (ret != 0) {
418 thread_error = 1;
419 LOGERR("Thread %i returned an error %i.\n", i, ret);
420 _exit(-1);
421 }
422 }
423 } else {
424 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
425 }
426 }
427 if (thread_error) {
428 LOGERR("Error returned by one or more threads.\n");
429 _exit(-1);
430 }
431 LOGINFO("Finished encrypted backup.\n");
432 _exit(0);
433 }
434 }
435 else // parent process
436 {
437 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
438 return -1;
439 }
440 }
441 else // fork has failed
442 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000443 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500444 return -1;
445 }
446 return 0;
447}
448
Dees_Troy83bd4832013-05-04 12:39:56 +0000449int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
450 DIR* d;
451 struct dirent* de;
452 struct stat st;
453 string FileName;
454 struct TarListStruct TarItem;
455 string::size_type i;
456 bool skip;
457
458 if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
459 return 0; // Skip /data/media
460
461 d = opendir(Path.c_str());
462 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000463 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000464 closedir(d);
465 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500466 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000467 while ((de = readdir(d)) != NULL) {
468 // Skip excluded stuff
Dees Troye0a433a2013-12-02 04:10:37 +0000469 FileName = Path + "/";
470 FileName += de->d_name;
471 if (tarexclude.size() > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000472 skip = false;
Dees Troye0a433a2013-12-02 04:10:37 +0000473 for (i = 0; i < tarexclude.size(); i++) {
474 if (FileName == tarexclude[i]) {
475 LOGINFO("Excluding %s\n", FileName.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000476 break;
477 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500478 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000479 if (skip)
480 continue;
481 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000482 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
483 continue; // Skip /data/media
484 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
485 continue;
486 TarItem.fn = FileName;
487 TarItem.thread_id = *thread_id;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500488 bool skip_dir = false;
489 string dir(de->d_name);
490 skip_dir = du.check_skip_dirs(dir);
491 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000492 TarList->push_back(TarItem);
493 if (Generate_TarList(FileName, TarList, Target_Size, thread_id) < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500494 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000495 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
496 stat(FileName.c_str(), &st);
497 TarList->push_back(TarItem);
498 if (de->d_type == DT_REG)
499 Archive_Current_Size += st.st_size;
500 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
501 *thread_id = *thread_id + 1;
502 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500503 }
504 }
505 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000506 closedir(d);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500507 return 0;
508}
509
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500510int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000511 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000512 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500513 return -1;
514 if (tar_extract_all(t, charRootDir) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000515 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500516 return -1;
517 }
518 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000519 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500520 return -1;
521 }
522 return 0;
523}
524
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500525int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000526 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200527
528 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500529 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000530 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000531 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500532 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600534 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000535 if (ret < 1) {
536 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
537 return -1;
538 }
539 if (ret == 1) {
540 LOGERR("Decrypted file is not in tar format.\n");
541 return -1;
542 }
543 if (ret == 3) {
544 LOGINFO("Extracting encrypted and compressed tar.\n");
545 Archive_Current_Type = 3;
546 } else
547 LOGINFO("Extracting encrypted tar.\n");
548 return extractTar();
549 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000550 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500551 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500552 }
553}
554
Dees Troye0a433a2013-12-02 04:10:37 +0000555int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000556 struct stat st;
557 char buf[PATH_MAX];
558 int list_size = TarList->size(), i = 0, archive_count = 0;
559 string temp;
560 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000561 char *ptr;
Dees_Troye34c1332013-02-06 19:13:00 +0000562
Dees Troye0a433a2013-12-02 04:10:37 +0000563 if (split_archives) {
564 basefn = tarfn;
565 temp = basefn + "%i%02i";
566 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
567 tarfn = actual_filename;
568 include_root_dir = true;
569 } else {
570 include_root_dir = false;
571 }
572 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000573 if (createTar() != 0) {
574 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
575 return -2;
576 }
577 Archive_Current_Size = 0;
578
579 while (i < list_size) {
580 if (TarList->at(i).thread_id == thread_id) {
581 strcpy(buf, TarList->at(i).fn.c_str());
582 stat(buf, &st);
583 if (st.st_mode & S_IFREG) { // item is a regular file
584 if (Archive_Current_Size + (unsigned long long)(st.st_size) > MAX_ARCHIVE_SIZE) {
585 if (closeTar() != 0) {
586 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
587 return -3;
588 }
589 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000590 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000591 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000592 LOGERR("Too many archives for thread %i\n", thread_id);
593 return -4;
594 }
595 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
596 tarfn = actual_filename;
597 if (createTar() != 0) {
598 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
599 return -2;
600 }
601 Archive_Current_Size = 0;
602 }
603 Archive_Current_Size += (unsigned long long)(st.st_size);
604 }
Dees Troye0a433a2013-12-02 04:10:37 +0000605 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
606 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000607 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
608 return -1;
609 }
610 }
611 i++;
612 }
613 if (closeTar() != 0) {
614 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
615 return -3;
616 }
617 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count, i, list_size);
Dees_Troye34c1332013-02-06 19:13:00 +0000618 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500619}
620
Dees_Troy83bd4832013-05-04 12:39:56 +0000621void* twrpTar::createList(void *cookie) {
622
623 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600624 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000625 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
626 return (void*)-2;
627 }
628 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
629 return (void*)0;
630}
631
632void* twrpTar::extractMulti(void *cookie) {
633
634 twrpTar* threadTar = (twrpTar*) cookie;
635 int archive_count = 0;
636 string temp = threadTar->basefn + "%i%02i";
637 char actual_filename[255];
638 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
639 while (TWFunc::Path_Exists(actual_filename)) {
640 threadTar->tarfn = actual_filename;
641 if (threadTar->extract() != 0) {
642 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
643 return (void*)-2;
644 }
645 archive_count++;
646 if (archive_count > 99)
647 break;
648 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
649 }
650 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
651 return (void*)0;
652}
653
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500654int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
655 char* charTarFile = (char*) fn.c_str();
656
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200657 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 -0500658 return -1;
659 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200660 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 -0500661 return -1;
662 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500663 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500664 if (tar_append_file(t, file, file) == -1)
665 return -1;
666 }
667 if (tar_append_eof(t) == -1)
668 return -1;
669 if (tar_close(t) == -1)
670 return -1;
671 return 0;
672}
673
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500674int twrpTar::createTar() {
675 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000676 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000677 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500678
Dees_Troy83bd4832013-05-04 12:39:56 +0000679 if (use_encryption && use_compression) {
680 // Compressed and encrypted
681 Archive_Current_Type = 3;
682 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000683 int i, pipes[4];
684
685 if (pipe(pipes) < 0) {
686 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500687 return -1;
688 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000689 if (pipe(pipes + 2) < 0) {
690 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500691 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000692 }
693 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400694
Dees_Troy83bd4832013-05-04 12:39:56 +0000695 if (pigz_pid < 0) {
696 LOGERR("pigz fork() failed\n");
697 for (i = 0; i < 4; i++)
698 close(pipes[i]); // close all
699 return -1;
700 } else if (pigz_pid == 0) {
701 // pigz Child
702 close(pipes[1]);
703 close(pipes[2]);
704 close(0);
705 dup2(pipes[0], 0);
706 close(1);
707 dup2(pipes[3], 1);
708 if (execlp("pigz", "pigz", "-", NULL) < 0) {
709 LOGERR("execlp pigz ERROR!\n");
710 close(pipes[0]);
711 close(pipes[3]);
712 _exit(-1);
713 }
714 } else {
715 // Parent
716 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400717
Dees_Troy83bd4832013-05-04 12:39:56 +0000718 if (oaes_pid < 0) {
719 LOGERR("openaes fork() failed\n");
720 for (i = 0; i < 4; i++)
721 close(pipes[i]); // close all
722 return -1;
723 } else if (oaes_pid == 0) {
724 // openaes Child
Dees_Troy5612cc82013-07-24 19:45:58 +0000725 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 +0000726 if (output_fd < 0) {
727 LOGERR("Failed to open '%s'\n", tarfn.c_str());
728 for (i = 0; i < 4; i++)
729 close(pipes[i]); // close all
730 return -1;
731 }
732 close(pipes[0]);
733 close(pipes[1]);
734 close(pipes[3]);
735 close(0);
736 dup2(pipes[2], 0);
737 close(1);
738 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600739 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000740 LOGERR("execlp openaes ERROR!\n");
741 close(pipes[2]);
742 close(output_fd);
743 _exit(-1);
744 }
745 } else {
746 // Parent
747 close(pipes[0]);
748 close(pipes[2]);
749 close(pipes[3]);
750 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200751 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 +0000752 close(fd);
753 LOGERR("tar_fdopen failed\n");
754 return -1;
755 }
756 return 0;
757 }
758 }
759 } else if (use_compression) {
760 // Compressed
761 Archive_Current_Type = 1;
762 LOGINFO("Using compression...\n");
763 int pigzfd[2];
764
765 if (pipe(pigzfd) < 0) {
766 LOGERR("Error creating pipe\n");
767 return -1;
768 }
769 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400770
Dees_Troy83bd4832013-05-04 12:39:56 +0000771 if (pigz_pid < 0) {
772 LOGERR("fork() failed\n");
773 close(pigzfd[0]);
774 close(pigzfd[1]);
775 return -1;
776 } else if (pigz_pid == 0) {
777 // Child
778 close(pigzfd[1]); // close unused output pipe
Dees_Troy5612cc82013-07-24 19:45:58 +0000779 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 +0000780 if (output_fd < 0) {
781 LOGERR("Failed to open '%s'\n", tarfn.c_str());
782 close(pigzfd[0]);
783 _exit(-1);
784 }
785 dup2(pigzfd[0], 0); // remap stdin
786 dup2(output_fd, 1); // remap stdout to output file
787 if (execlp("pigz", "pigz", "-", NULL) < 0) {
788 LOGERR("execlp pigz ERROR!\n");
789 close(output_fd);
790 close(pigzfd[0]);
791 _exit(-1);
792 }
793 } else {
794 // Parent
795 close(pigzfd[0]); // close parent input
796 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200797 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 +0000798 close(fd);
799 LOGERR("tar_fdopen failed\n");
800 return -1;
801 }
802 }
803 } else if (use_encryption) {
804 // Encrypted
805 Archive_Current_Type = 2;
806 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000807 int oaesfd[2];
808 pipe(oaesfd);
809 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400810
Dees_Troy83bd4832013-05-04 12:39:56 +0000811 if (oaes_pid < 0) {
812 LOGERR("fork() failed\n");
813 close(oaesfd[0]);
814 close(oaesfd[1]);
815 return -1;
816 } else if (oaes_pid == 0) {
817 // Child
818 close(oaesfd[1]); // close unused
Dees_Troy5612cc82013-07-24 19:45:58 +0000819 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 +0000820 if (output_fd < 0) {
821 LOGERR("Failed to open '%s'\n", tarfn.c_str());
822 _exit(-1);
823 }
824 dup2(oaesfd[0], 0); // remap stdin
825 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600826 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000827 LOGERR("execlp openaes ERROR!\n");
828 close(output_fd);
829 close(oaesfd[0]);
830 _exit(-1);
831 }
832 } else {
833 // Parent
834 close(oaesfd[0]); // close parent input
835 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200836 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 +0000837 close(fd);
838 LOGERR("tar_fdopen failed\n");
839 return -1;
840 }
841 return 0;
842 }
843 } else {
844 // Not compressed or encrypted
845 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200846 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 +0000847 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
848 return -1;
849 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500850 }
851 return 0;
852}
853
Dees_Troy83bd4832013-05-04 12:39:56 +0000854int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000855 char* charRootDir = (char*) tardir.c_str();
856 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000857 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500858
Dees_Troy83bd4832013-05-04 12:39:56 +0000859 if (Archive_Current_Type == 3) {
860 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000861 int i, pipes[4];
862
863 if (pipe(pipes) < 0) {
864 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500865 return -1;
866 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000867 if (pipe(pipes + 2) < 0) {
868 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500869 return -1;
870 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000871 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400872
Dees_Troy83bd4832013-05-04 12:39:56 +0000873 if (oaes_pid < 0) {
874 LOGERR("pigz fork() failed\n");
875 for (i = 0; i < 4; i++)
876 close(pipes[i]); // close all
877 return -1;
878 } else if (oaes_pid == 0) {
879 // openaes Child
880 close(pipes[0]); // Close pipes that are not used by this child
881 close(pipes[2]);
882 close(pipes[3]);
883 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
884 if (input_fd < 0) {
885 LOGERR("Failed to open '%s'\n", tarfn.c_str());
886 close(pipes[1]);
887 _exit(-1);
888 }
889 close(0);
890 dup2(input_fd, 0);
891 close(1);
892 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600893 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000894 LOGERR("execlp openaes ERROR!\n");
895 close(input_fd);
896 close(pipes[1]);
897 _exit(-1);
898 }
899 } else {
900 // Parent
901 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400902
Dees_Troy83bd4832013-05-04 12:39:56 +0000903 if (pigz_pid < 0) {
904 LOGERR("openaes fork() failed\n");
905 for (i = 0; i < 4; i++)
906 close(pipes[i]); // close all
907 return -1;
908 } else if (pigz_pid == 0) {
909 // pigz Child
910 close(pipes[1]); // Close pipes not used by this child
911 close(pipes[2]);
912 close(0);
913 dup2(pipes[0], 0);
914 close(1);
915 dup2(pipes[3], 1);
916 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
917 LOGERR("execlp pigz ERROR!\n");
918 close(pipes[0]);
919 close(pipes[3]);
920 _exit(-1);
921 }
922 } else {
923 // Parent
924 close(pipes[0]); // Close pipes not used by parent
925 close(pipes[1]);
926 close(pipes[3]);
927 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200928 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 +0000929 close(fd);
930 LOGERR("tar_fdopen failed\n");
931 return -1;
932 }
933 }
934 }
935 } else if (Archive_Current_Type == 2) {
936 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000937 int oaesfd[2];
938
939 pipe(oaesfd);
940 oaes_pid = fork();
941 if (oaes_pid < 0) {
942 LOGERR("fork() failed\n");
943 close(oaesfd[0]);
944 close(oaesfd[1]);
945 return -1;
946 } else if (oaes_pid == 0) {
947 // Child
948 close(oaesfd[0]); // Close unused pipe
949 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
950 if (input_fd < 0) {
951 LOGERR("Failed to open '%s'\n", tarfn.c_str());
952 close(oaesfd[1]);
953 _exit(-1);
954 }
955 close(0); // close stdin
956 dup2(oaesfd[1], 1); // remap stdout
957 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -0600958 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000959 LOGERR("execlp openaes ERROR!\n");
960 close(input_fd);
961 close(oaesfd[1]);
962 _exit(-1);
963 }
964 } else {
965 // Parent
966 close(oaesfd[1]); // close parent output
967 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200968 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 +0000969 close(fd);
970 LOGERR("tar_fdopen failed\n");
971 return -1;
972 }
973 }
974 } else if (Archive_Current_Type == 1) {
975 LOGINFO("Opening as a gzip...\n");
976 int pigzfd[2];
977 pipe(pigzfd);
978
979 pigz_pid = fork();
980 if (pigz_pid < 0) {
981 LOGERR("fork() failed\n");
982 close(pigzfd[0]);
983 close(pigzfd[1]);
984 return -1;
985 } else if (pigz_pid == 0) {
986 // Child
987 close(pigzfd[0]);
988 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
989 if (input_fd < 0) {
990 LOGERR("Failed to open '%s'\n", tarfn.c_str());
991 _exit(-1);
992 }
993 dup2(input_fd, 0); // remap input fd to stdin
994 dup2(pigzfd[1], 1); // remap stdout
995 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
996 close(pigzfd[1]);
997 close(input_fd);
998 LOGERR("execlp openaes ERROR!\n");
999 _exit(-1);
1000 }
1001 } else {
1002 // Parent
1003 close(pigzfd[1]); // close parent output
1004 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001005 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 +00001006 close(fd);
1007 LOGERR("tar_fdopen failed\n");
1008 return -1;
1009 }
1010 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001011 } 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 +00001012 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1013 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001014 }
1015 return 0;
1016}
1017
1018string twrpTar::Strip_Root_Dir(string Path) {
1019 string temp;
1020 size_t slash;
1021
1022 if (Path.substr(0, 1) == "/")
1023 temp = Path.substr(1, Path.size() - 1);
1024 else
1025 temp = Path;
1026 slash = temp.find("/");
1027 if (slash == string::npos)
1028 return temp;
1029 else {
1030 string stripped;
1031
1032 stripped = temp.substr(slash, temp.size() - slash);
1033 return stripped;
1034 }
1035 return temp;
1036}
1037
1038int twrpTar::addFile(string fn, bool include_root) {
1039 char* charTarFile = (char*) fn.c_str();
1040 if (include_root) {
1041 if (tar_append_file(t, charTarFile, NULL) == -1)
1042 return -1;
1043 } else {
1044 string temp = Strip_Root_Dir(fn);
1045 char* charTarPath = (char*) temp.c_str();
1046 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1047 return -1;
1048 }
1049 return 0;
1050}
1051
Dees_Troy83bd4832013-05-04 12:39:56 +00001052int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001053 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001054 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001055 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001056 tar_close(t);
1057 return -1;
1058 }
1059 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001060 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001061 return -1;
1062 }
Dees_Troy2727b992013-08-14 20:09:30 +00001063 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001064 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001065 int status;
1066 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1067 return -1;
1068 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1069 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001070 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001071 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001072 if (use_compression && !use_encryption) {
1073 string gzname = tarfn + ".gz";
1074 if (TWFunc::Path_Exists(gzname)) {
1075 rename(gzname.c_str(), tarfn.c_str());
1076 }
1077 }
1078 if (TWFunc::Get_File_Size(tarfn) == 0) {
1079 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1080 return -1;
1081 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001082 return 0;
1083}
1084
1085int twrpTar::removeEOT(string tarFile) {
1086 char* charTarFile = (char*) tarFile.c_str();
1087 off_t tarFileEnd;
1088 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001089 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001090 tar_skip_regfile(t);
1091 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001092 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001093 if (tar_close(t) == -1)
1094 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001095 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001096 return -1;
1097 return 0;
1098}
1099
n0d33b511632013-03-06 21:14:15 +02001100int twrpTar::entryExists(string entry) {
1101 char* searchstr = (char*)entry.c_str();
1102 int ret;
1103
Dees_Troy83bd4832013-05-04 12:39:56 +00001104 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001105
Dees_Troy83bd4832013-05-04 12:39:56 +00001106 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001107 ret = 0;
1108 else
1109 ret = tar_find(t, searchstr);
1110
Dees_Troy83bd4832013-05-04 12:39:56 +00001111 if (closeTar() != 0)
1112 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001113
1114 return ret;
1115}
1116
Dees_Troye34c1332013-02-06 19:13:00 +00001117extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1118 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001119}