blob: 824356aaefbb7cbcfa9aedcad1fd6c05227ec28a [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"
Dees_Troy40bbcf82013-02-12 15:01:53 +000024 #include "libcrecovery/common.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050025}
26#include <sys/types.h>
27#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050028#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050029#include <string.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050033#include <iostream>
34#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050035#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000036#include <vector>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050037#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040038#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050039#include <sys/mman.h>
40#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000041#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050042#include "data.hpp"
43#include "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050044#include "twrp-functions.hpp"
45
46using namespace std;
47
Dees_Troy83bd4832013-05-04 12:39:56 +000048twrpTar::twrpTar(void) {
49 use_encryption = 0;
50 userdata_encryption = 0;
51 use_compression = 0;
52 split_archives = 0;
53 has_data_media = 0;
54 pigz_pid = 0;
55 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000056 Total_Backup_Size = 0;
57 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000058}
59
60twrpTar::~twrpTar(void) {
61 // Do nothing
62}
63
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050064void twrpTar::setfn(string fn) {
65 tarfn = fn;
66}
67
68void twrpTar::setdir(string dir) {
69 tardir = dir;
70}
71
Dees_Troy83bd4832013-05-04 12:39:56 +000072void twrpTar::setexcl(string exclude) {
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -040073 tarexclude.push_back(exclude);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050074}
75
Dees Troye0a433a2013-12-02 04:10:37 +000076void twrpTar::setsize(unsigned long long backup_size) {
77 Total_Backup_Size = backup_size;
78}
79
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050080int twrpTar::createTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +000081 int status = 0;
82 pid_t pid, rc_pid;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050083 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000084 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050085 return -1;
86 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050087 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +000088 // Child process
89 if (use_encryption || userdata_encryption) {
90 LOGINFO("Using encryption\n");
91 DIR* d;
92 struct dirent* de;
93 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1;
94 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
95 int item_len, ret, thread_error = 0;
96 std::vector<TarListStruct> RegularList;
97 std::vector<TarListStruct> EncryptList;
98 string FileName;
99 struct TarListStruct TarItem;
100 twrpTar reg, enc[9];
101 struct stat st;
102 pthread_t enc_thread[9];
103 pthread_attr_t tattr;
104 void *thread_return;
105
106 core_count = sysconf(_SC_NPROCESSORS_CONF);
107 if (core_count > 8)
108 core_count = 8;
109 LOGINFO(" Core Count : %llu\n", core_count);
110 Archive_Current_Size = 0;
111
112 d = opendir(tardir.c_str());
113 if (d == NULL) {
114 LOGERR("error opening '%s'\n", tardir.c_str());
115 _exit(-1);
116 }
117 // Figure out the size of all data to be encrypted and create a list of unencrypted files
118 while ((de = readdir(d)) != NULL) {
119 FileName = tardir + "/";
120 FileName += de->d_name;
121 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
122 continue; // Skip /data/media
123 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
124 continue;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500125 bool skip_dir = false;
126 string dir(de->d_name);
127 skip_dir = du.check_skip_dirs(dir);
128 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000129 item_len = strlen(de->d_name);
130 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
131 if (Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id) < 0) {
132 LOGERR("Error in Generate_TarList with regular list!\n");
133 closedir(d);
134 _exit(-1);
135 }
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500136 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000137 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500138 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000139 }
140 } else if (de->d_type == DT_REG) {
141 stat(FileName.c_str(), &st);
142 encrypt_size += (unsigned long long)(st.st_size);
143 }
144 }
145 closedir(d);
146
147 target_size = encrypt_size / core_count;
148 target_size++;
149 LOGINFO(" Unencrypted size: %llu\n", regular_size);
150 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
151 LOGINFO(" Target size : %llu\n", target_size);
152 if (!userdata_encryption) {
153 enc_thread_id = 0;
154 start_thread_id = 0;
155 core_count--;
156 }
157 Archive_Current_Size = 0;
158
159 d = opendir(tardir.c_str());
160 if (d == NULL) {
161 LOGERR("error opening '%s'\n", tardir.c_str());
162 _exit(-1);
163 }
164 // Divide up the encrypted file list for threading
165 while ((de = readdir(d)) != NULL) {
166 FileName = tardir + "/";
167 FileName += de->d_name;
168 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
169 continue; // Skip /data/media
170 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
171 continue;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500172 bool skip_dir = false;
173 string dir(de->d_name);
174 skip_dir = du.check_skip_dirs(dir);
175 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000176 item_len = strlen(de->d_name);
177 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
178 // Do nothing, we added these to RegularList earlier
179 } else {
180 FileName = tardir + "/";
181 FileName += de->d_name;
182 if (Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id) < 0) {
183 LOGERR("Error in Generate_TarList with encrypted list!\n");
184 closedir(d);
185 _exit(-1);
186 }
187 }
188 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
189 stat(FileName.c_str(), &st);
190 if (de->d_type == DT_REG)
191 Archive_Current_Size += (unsigned long long)(st.st_size);
192 TarItem.fn = FileName;
193 TarItem.thread_id = enc_thread_id;
194 EncryptList.push_back(TarItem);
195 }
196 }
197 closedir(d);
198 if (enc_thread_id != core_count) {
199 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
200 if (enc_thread_id > core_count)
201 _exit(-1);
202 else
203 LOGERR("Continuining anyway.");
204 }
205
206 if (userdata_encryption) {
207 // Create a backup of unencrypted data
208 reg.setfn(tarfn);
209 reg.ItemList = &RegularList;
210 reg.thread_id = 0;
211 reg.use_encryption = 0;
212 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000213 reg.split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000214 LOGINFO("Creating unencrypted backup...\n");
215 if (createList((void*)&reg) != 0) {
216 LOGERR("Error creating unencrypted backup.\n");
217 _exit(-1);
218 }
219 }
220
221 if (pthread_attr_init(&tattr)) {
222 LOGERR("Unable to pthread_attr_init\n");
223 _exit(-1);
224 }
225 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
226 LOGERR("Error setting pthread_attr_setdetachstate\n");
227 _exit(-1);
228 }
229 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
230 LOGERR("Error setting pthread_attr_setscope\n");
231 _exit(-1);
232 }
233 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
234 LOGERR("Error setting pthread_attr_setstacksize\n");
235 _exit(-1);
236 }*/
237
238 // Create threads for the divided up encryption lists
239 for (i = start_thread_id; i <= core_count; i++) {
240 enc[i].setdir(tardir);
241 enc[i].setfn(tarfn);
242 enc[i].ItemList = &EncryptList;
243 enc[i].thread_id = i;
244 enc[i].use_encryption = use_encryption;
245 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000246 enc[i].split_archives = 1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000247 LOGINFO("Start encryption thread %i\n", i);
248 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
249 if (ret) {
250 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).", i, ret);
251 if (createList((void*)&enc[i]) != 0) {
252 LOGERR("Error creating encrypted backup %i.\n", i);
253 _exit(-1);
254 } else {
255 enc[i].thread_id = i + 1;
256 }
257 }
258 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
259 }
260 if (pthread_attr_destroy(&tattr)) {
261 LOGERR("Failed to pthread_attr_destroy\n");
262 }
263 for (i = start_thread_id; i <= core_count; i++) {
264 if (enc[i].thread_id == i) {
265 if (pthread_join(enc_thread[i], &thread_return)) {
266 LOGERR("Error joining thread %i\n", i);
267 _exit(-1);
268 } else {
269 LOGINFO("Joined thread %i.\n", i);
270 ret = (int)thread_return;
271 if (ret != 0) {
272 thread_error = 1;
273 LOGERR("Thread %i returned an error %i.\n", i, ret);
274 _exit(-1);
275 }
276 }
277 } else {
278 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
279 }
280 }
281 if (thread_error) {
282 LOGERR("Error returned by one or more threads.\n");
283 _exit(-1);
284 }
285 LOGINFO("Finished encrypted backup.\n");
286 _exit(0);
287 } else {
Dees Troye0a433a2013-12-02 04:10:37 +0000288 std::vector<TarListStruct> FileList;
289 unsigned thread_id = 0;
290 unsigned long long target_size = 0;
291 twrpTar reg;
292
293 // Generate list of files to back up
294 if (Generate_TarList(tardir, &FileList, &target_size, &thread_id) < 0) {
295 LOGERR("Error in Generate_TarList!\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000296 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000297 }
298 // Create a backup
299 reg.setfn(tarfn);
300 reg.ItemList = &FileList;
301 reg.thread_id = 0;
302 reg.use_encryption = 0;
303 reg.use_compression = use_compression;
304 reg.setsize(Total_Backup_Size);
305 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
306 gui_print("Breaking backup file into multiple archives...\n");
307 reg.split_archives = 1;
308 } else {
309 reg.split_archives = 0;
310 }
311 LOGINFO("Creating backup...\n");
312 if (createList((void*)&reg) != 0) {
313 LOGERR("Error creating backup.\n");
314 _exit(-1);
315 }
316 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000317 }
318 } else {
319 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500320 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500321 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500322 return 0;
323}
324
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500325int twrpTar::extractTarFork() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000326 int status = 0;
327 pid_t pid, rc_pid;
328
329 pid = fork();
330 if (pid >= 0) // fork was successful
331 {
332 if (pid == 0) // child process
333 {
334 if (TWFunc::Path_Exists(tarfn)) {
335 LOGINFO("Single archive\n");
336 if (extract() != 0)
337 _exit(-1);
338 else
339 _exit(0);
340 } else {
341 LOGINFO("Multiple archives\n");
342 string temp;
343 char actual_filename[255];
344 twrpTar tars[9];
345 pthread_t tar_thread[9];
346 pthread_attr_t tattr;
347 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
348 void *thread_return;
349
350 basefn = tarfn;
351 temp = basefn + "%i%02i";
352 tarfn += "000";
353 if (!TWFunc::Path_Exists(tarfn)) {
354 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
355 _exit(-1);
356 }
357 if (TWFunc::Get_File_Type(tarfn) != 2) {
358 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
359 tars[0].basefn = basefn;
360 tars[0].thread_id = 0;
361 if (extractMulti((void*)&tars[0]) != 0) {
362 LOGERR("Error extracting split archive.\n");
363 _exit(-1);
364 }
365 } else {
366 start_thread_id = 0;
367 }
368 // Start threading encrypted restores
369 if (pthread_attr_init(&tattr)) {
370 LOGERR("Unable to pthread_attr_init\n");
371 _exit(-1);
372 }
373 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
374 LOGERR("Error setting pthread_attr_setdetachstate\n");
375 _exit(-1);
376 }
377 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
378 LOGERR("Error setting pthread_attr_setscope\n");
379 _exit(-1);
380 }
381 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
382 LOGERR("Error setting pthread_attr_setstacksize\n");
383 _exit(-1);
384 }*/
385 for (i = start_thread_id; i < 9; i++) {
386 sprintf(actual_filename, temp.c_str(), i, 0);
387 if (TWFunc::Path_Exists(actual_filename)) {
388 thread_count++;
389 tars[i].basefn = basefn;
390 tars[i].thread_id = i;
391 LOGINFO("Creating extract thread ID %i\n", i);
392 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
393 if (ret) {
394 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).", i, ret);
395 if (extractMulti((void*)&tars[i]) != 0) {
396 LOGERR("Error extracting backup in thread %i.\n", i);
397 _exit(-1);
398 } else {
399 tars[i].thread_id = i + 1;
400 }
401 }
402 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
403 } else {
404 break;
405 }
406 }
407 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
408 if (tars[i].thread_id == i) {
409 if (pthread_join(tar_thread[i], &thread_return)) {
410 LOGERR("Error joining thread %i\n", i);
411 _exit(-1);
412 } else {
413 LOGINFO("Joined thread %i.\n", i);
414 ret = (int)thread_return;
415 if (ret != 0) {
416 thread_error = 1;
417 LOGERR("Thread %i returned an error %i.\n", i, ret);
418 _exit(-1);
419 }
420 }
421 } else {
422 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
423 }
424 }
425 if (thread_error) {
426 LOGERR("Error returned by one or more threads.\n");
427 _exit(-1);
428 }
429 LOGINFO("Finished encrypted backup.\n");
430 _exit(0);
431 }
432 }
433 else // parent process
434 {
435 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
436 return -1;
437 }
438 }
439 else // fork has failed
440 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000441 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500442 return -1;
443 }
444 return 0;
445}
446
Dees_Troy83bd4832013-05-04 12:39:56 +0000447int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
448 DIR* d;
449 struct dirent* de;
450 struct stat st;
451 string FileName;
452 struct TarListStruct TarItem;
453 string::size_type i;
454 bool skip;
455
456 if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
457 return 0; // Skip /data/media
458
459 d = opendir(Path.c_str());
460 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000461 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000462 closedir(d);
463 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500464 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000465 while ((de = readdir(d)) != NULL) {
466 // Skip excluded stuff
Dees Troye0a433a2013-12-02 04:10:37 +0000467 FileName = Path + "/";
468 FileName += de->d_name;
469 if (tarexclude.size() > 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000470 skip = false;
Dees Troye0a433a2013-12-02 04:10:37 +0000471 for (i = 0; i < tarexclude.size(); i++) {
472 if (FileName == tarexclude[i]) {
473 LOGINFO("Excluding %s\n", FileName.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000474 break;
475 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500476 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000477 if (skip)
478 continue;
479 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000480 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
481 continue; // Skip /data/media
482 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
483 continue;
484 TarItem.fn = FileName;
485 TarItem.thread_id = *thread_id;
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500486 bool skip_dir = false;
487 string dir(de->d_name);
488 skip_dir = du.check_skip_dirs(dir);
489 if (de->d_type == DT_DIR && !skip_dir) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000490 TarList->push_back(TarItem);
491 if (Generate_TarList(FileName, TarList, Target_Size, thread_id) < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500492 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000493 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
494 stat(FileName.c_str(), &st);
495 TarList->push_back(TarItem);
496 if (de->d_type == DT_REG)
497 Archive_Current_Size += st.st_size;
498 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
499 *thread_id = *thread_id + 1;
500 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500501 }
502 }
503 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000504 closedir(d);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500505 return 0;
506}
507
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500508int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000509 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000510 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500511 return -1;
512 if (tar_extract_all(t, charRootDir) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000513 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500514 return -1;
515 }
516 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000517 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500518 return -1;
519 }
520 return 0;
521}
522
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500523int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000524 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200525
526 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500527 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000528 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000529 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500530 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000531 } else if (Archive_Current_Type == 2) {
532 string Password;
533 DataManager::GetValue("tw_restore_password", Password);
534 int ret = TWFunc::Try_Decrypting_File(tarfn, Password);
535 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;
Dees Troye0a433a2013-12-02 04:10:37 +0000624 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) == -1) {
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 };
Dees_Troy83bd4832013-05-04 12:39:56 +0000678 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500679
Dees_Troy83bd4832013-05-04 12:39:56 +0000680 if (use_encryption && use_compression) {
681 // Compressed and encrypted
682 Archive_Current_Type = 3;
683 LOGINFO("Using encryption and compression...\n");
684 DataManager::GetValue("tw_backup_password", Password);
685 int i, pipes[4];
686
687 if (pipe(pipes) < 0) {
688 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500689 return -1;
690 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 if (pipe(pipes + 2) < 0) {
692 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500693 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000694 }
695 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400696
Dees_Troy83bd4832013-05-04 12:39:56 +0000697 if (pigz_pid < 0) {
698 LOGERR("pigz fork() failed\n");
699 for (i = 0; i < 4; i++)
700 close(pipes[i]); // close all
701 return -1;
702 } else if (pigz_pid == 0) {
703 // pigz Child
704 close(pipes[1]);
705 close(pipes[2]);
706 close(0);
707 dup2(pipes[0], 0);
708 close(1);
709 dup2(pipes[3], 1);
710 if (execlp("pigz", "pigz", "-", NULL) < 0) {
711 LOGERR("execlp pigz ERROR!\n");
712 close(pipes[0]);
713 close(pipes[3]);
714 _exit(-1);
715 }
716 } else {
717 // Parent
718 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400719
Dees_Troy83bd4832013-05-04 12:39:56 +0000720 if (oaes_pid < 0) {
721 LOGERR("openaes fork() failed\n");
722 for (i = 0; i < 4; i++)
723 close(pipes[i]); // close all
724 return -1;
725 } else if (oaes_pid == 0) {
726 // openaes Child
Dees_Troy5612cc82013-07-24 19:45:58 +0000727 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 +0000728 if (output_fd < 0) {
729 LOGERR("Failed to open '%s'\n", tarfn.c_str());
730 for (i = 0; i < 4; i++)
731 close(pipes[i]); // close all
732 return -1;
733 }
734 close(pipes[0]);
735 close(pipes[1]);
736 close(pipes[3]);
737 close(0);
738 dup2(pipes[2], 0);
739 close(1);
740 dup2(output_fd, 1);
741 if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) {
742 LOGERR("execlp openaes ERROR!\n");
743 close(pipes[2]);
744 close(output_fd);
745 _exit(-1);
746 }
747 } else {
748 // Parent
749 close(pipes[0]);
750 close(pipes[2]);
751 close(pipes[3]);
752 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200753 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 +0000754 close(fd);
755 LOGERR("tar_fdopen failed\n");
756 return -1;
757 }
758 return 0;
759 }
760 }
761 } else if (use_compression) {
762 // Compressed
763 Archive_Current_Type = 1;
764 LOGINFO("Using compression...\n");
765 int pigzfd[2];
766
767 if (pipe(pigzfd) < 0) {
768 LOGERR("Error creating pipe\n");
769 return -1;
770 }
771 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400772
Dees_Troy83bd4832013-05-04 12:39:56 +0000773 if (pigz_pid < 0) {
774 LOGERR("fork() failed\n");
775 close(pigzfd[0]);
776 close(pigzfd[1]);
777 return -1;
778 } else if (pigz_pid == 0) {
779 // Child
780 close(pigzfd[1]); // close unused output pipe
Dees_Troy5612cc82013-07-24 19:45:58 +0000781 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 +0000782 if (output_fd < 0) {
783 LOGERR("Failed to open '%s'\n", tarfn.c_str());
784 close(pigzfd[0]);
785 _exit(-1);
786 }
787 dup2(pigzfd[0], 0); // remap stdin
788 dup2(output_fd, 1); // remap stdout to output file
789 if (execlp("pigz", "pigz", "-", NULL) < 0) {
790 LOGERR("execlp pigz ERROR!\n");
791 close(output_fd);
792 close(pigzfd[0]);
793 _exit(-1);
794 }
795 } else {
796 // Parent
797 close(pigzfd[0]); // close parent input
798 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200799 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 +0000800 close(fd);
801 LOGERR("tar_fdopen failed\n");
802 return -1;
803 }
804 }
805 } else if (use_encryption) {
806 // Encrypted
807 Archive_Current_Type = 2;
808 LOGINFO("Using encryption...\n");
809 DataManager::GetValue("tw_backup_password", Password);
810 int oaesfd[2];
811 pipe(oaesfd);
812 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400813
Dees_Troy83bd4832013-05-04 12:39:56 +0000814 if (oaes_pid < 0) {
815 LOGERR("fork() failed\n");
816 close(oaesfd[0]);
817 close(oaesfd[1]);
818 return -1;
819 } else if (oaes_pid == 0) {
820 // Child
821 close(oaesfd[1]); // close unused
Dees_Troy5612cc82013-07-24 19:45:58 +0000822 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 +0000823 if (output_fd < 0) {
824 LOGERR("Failed to open '%s'\n", tarfn.c_str());
825 _exit(-1);
826 }
827 dup2(oaesfd[0], 0); // remap stdin
828 dup2(output_fd, 1); // remap stdout to output file
829 if (execlp("openaes", "openaes", "enc", "--key", Password.c_str(), NULL) < 0) {
830 LOGERR("execlp openaes ERROR!\n");
831 close(output_fd);
832 close(oaesfd[0]);
833 _exit(-1);
834 }
835 } else {
836 // Parent
837 close(oaesfd[0]); // close parent input
838 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200839 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 +0000840 close(fd);
841 LOGERR("tar_fdopen failed\n");
842 return -1;
843 }
844 return 0;
845 }
846 } else {
847 // Not compressed or encrypted
848 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200849 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 +0000850 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
851 return -1;
852 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500853 }
854 return 0;
855}
856
Dees_Troy83bd4832013-05-04 12:39:56 +0000857int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000858 char* charRootDir = (char*) tardir.c_str();
859 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000860 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500861
Dees_Troy83bd4832013-05-04 12:39:56 +0000862 if (Archive_Current_Type == 3) {
863 LOGINFO("Opening encrypted and compressed backup...\n");
864 DataManager::GetValue("tw_restore_password", Password);
865 int i, pipes[4];
866
867 if (pipe(pipes) < 0) {
868 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500869 return -1;
870 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000871 if (pipe(pipes + 2) < 0) {
872 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500873 return -1;
874 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000875 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400876
Dees_Troy83bd4832013-05-04 12:39:56 +0000877 if (oaes_pid < 0) {
878 LOGERR("pigz fork() failed\n");
879 for (i = 0; i < 4; i++)
880 close(pipes[i]); // close all
881 return -1;
882 } else if (oaes_pid == 0) {
883 // openaes Child
884 close(pipes[0]); // Close pipes that are not used by this child
885 close(pipes[2]);
886 close(pipes[3]);
887 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
888 if (input_fd < 0) {
889 LOGERR("Failed to open '%s'\n", tarfn.c_str());
890 close(pipes[1]);
891 _exit(-1);
892 }
893 close(0);
894 dup2(input_fd, 0);
895 close(1);
896 dup2(pipes[1], 1);
897 if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) {
898 LOGERR("execlp openaes ERROR!\n");
899 close(input_fd);
900 close(pipes[1]);
901 _exit(-1);
902 }
903 } else {
904 // Parent
905 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400906
Dees_Troy83bd4832013-05-04 12:39:56 +0000907 if (pigz_pid < 0) {
908 LOGERR("openaes fork() failed\n");
909 for (i = 0; i < 4; i++)
910 close(pipes[i]); // close all
911 return -1;
912 } else if (pigz_pid == 0) {
913 // pigz Child
914 close(pipes[1]); // Close pipes not used by this child
915 close(pipes[2]);
916 close(0);
917 dup2(pipes[0], 0);
918 close(1);
919 dup2(pipes[3], 1);
920 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
921 LOGERR("execlp pigz ERROR!\n");
922 close(pipes[0]);
923 close(pipes[3]);
924 _exit(-1);
925 }
926 } else {
927 // Parent
928 close(pipes[0]); // Close pipes not used by parent
929 close(pipes[1]);
930 close(pipes[3]);
931 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200932 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 +0000933 close(fd);
934 LOGERR("tar_fdopen failed\n");
935 return -1;
936 }
937 }
938 }
939 } else if (Archive_Current_Type == 2) {
940 LOGINFO("Opening encrypted backup...\n");
941 DataManager::GetValue("tw_restore_password", Password);
942 int oaesfd[2];
943
944 pipe(oaesfd);
945 oaes_pid = fork();
946 if (oaes_pid < 0) {
947 LOGERR("fork() failed\n");
948 close(oaesfd[0]);
949 close(oaesfd[1]);
950 return -1;
951 } else if (oaes_pid == 0) {
952 // Child
953 close(oaesfd[0]); // Close unused pipe
954 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
955 if (input_fd < 0) {
956 LOGERR("Failed to open '%s'\n", tarfn.c_str());
957 close(oaesfd[1]);
958 _exit(-1);
959 }
960 close(0); // close stdin
961 dup2(oaesfd[1], 1); // remap stdout
962 dup2(input_fd, 0); // remap input fd to stdin
963 if (execlp("openaes", "openaes", "dec", "--key", Password.c_str(), NULL) < 0) {
964 LOGERR("execlp openaes ERROR!\n");
965 close(input_fd);
966 close(oaesfd[1]);
967 _exit(-1);
968 }
969 } else {
970 // Parent
971 close(oaesfd[1]); // close parent output
972 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200973 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 +0000974 close(fd);
975 LOGERR("tar_fdopen failed\n");
976 return -1;
977 }
978 }
979 } else if (Archive_Current_Type == 1) {
980 LOGINFO("Opening as a gzip...\n");
981 int pigzfd[2];
982 pipe(pigzfd);
983
984 pigz_pid = fork();
985 if (pigz_pid < 0) {
986 LOGERR("fork() failed\n");
987 close(pigzfd[0]);
988 close(pigzfd[1]);
989 return -1;
990 } else if (pigz_pid == 0) {
991 // Child
992 close(pigzfd[0]);
993 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
994 if (input_fd < 0) {
995 LOGERR("Failed to open '%s'\n", tarfn.c_str());
996 _exit(-1);
997 }
998 dup2(input_fd, 0); // remap input fd to stdin
999 dup2(pigzfd[1], 1); // remap stdout
1000 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1001 close(pigzfd[1]);
1002 close(input_fd);
1003 LOGERR("execlp openaes ERROR!\n");
1004 _exit(-1);
1005 }
1006 } else {
1007 // Parent
1008 close(pigzfd[1]); // close parent output
1009 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001010 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 +00001011 close(fd);
1012 LOGERR("tar_fdopen failed\n");
1013 return -1;
1014 }
1015 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001016 } 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 +00001017 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1018 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001019 }
1020 return 0;
1021}
1022
1023string twrpTar::Strip_Root_Dir(string Path) {
1024 string temp;
1025 size_t slash;
1026
1027 if (Path.substr(0, 1) == "/")
1028 temp = Path.substr(1, Path.size() - 1);
1029 else
1030 temp = Path;
1031 slash = temp.find("/");
1032 if (slash == string::npos)
1033 return temp;
1034 else {
1035 string stripped;
1036
1037 stripped = temp.substr(slash, temp.size() - slash);
1038 return stripped;
1039 }
1040 return temp;
1041}
1042
1043int twrpTar::addFile(string fn, bool include_root) {
1044 char* charTarFile = (char*) fn.c_str();
1045 if (include_root) {
1046 if (tar_append_file(t, charTarFile, NULL) == -1)
1047 return -1;
1048 } else {
1049 string temp = Strip_Root_Dir(fn);
1050 char* charTarPath = (char*) temp.c_str();
1051 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1052 return -1;
1053 }
1054 return 0;
1055}
1056
Dees_Troy83bd4832013-05-04 12:39:56 +00001057int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001058 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001059 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001060 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001061 tar_close(t);
1062 return -1;
1063 }
1064 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001065 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001066 return -1;
1067 }
Dees_Troy2727b992013-08-14 20:09:30 +00001068 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001069 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001070 int status;
1071 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1072 return -1;
1073 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1074 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001075 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001076 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001077 if (use_compression && !use_encryption) {
1078 string gzname = tarfn + ".gz";
1079 if (TWFunc::Path_Exists(gzname)) {
1080 rename(gzname.c_str(), tarfn.c_str());
1081 }
1082 }
1083 if (TWFunc::Get_File_Size(tarfn) == 0) {
1084 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1085 return -1;
1086 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001087 return 0;
1088}
1089
1090int twrpTar::removeEOT(string tarFile) {
1091 char* charTarFile = (char*) tarFile.c_str();
1092 off_t tarFileEnd;
1093 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001094 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001095 tar_skip_regfile(t);
1096 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001097 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001098 if (tar_close(t) == -1)
1099 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001100 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001101 return -1;
1102 return 0;
1103}
1104
n0d33b511632013-03-06 21:14:15 +02001105int twrpTar::entryExists(string entry) {
1106 char* searchstr = (char*)entry.c_str();
1107 int ret;
1108
Dees_Troy83bd4832013-05-04 12:39:56 +00001109 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001110
Dees_Troy83bd4832013-05-04 12:39:56 +00001111 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001112 ret = 0;
1113 else
1114 ret = tar_find(t, searchstr);
1115
Dees_Troy83bd4832013-05-04 12:39:56 +00001116 if (closeTar() != 0)
1117 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001118
1119 return ret;
1120}
1121
Dees_Troy83bd4832013-05-04 12:39:56 +00001122unsigned long long twrpTar::uncompressedSize() {
1123 int type = 0;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001124 unsigned long long total_size = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +00001125 string Tar, Command, result;
1126 vector<string> split;
1127
1128 Tar = TWFunc::Get_Filename(tarfn);
1129 type = TWFunc::Get_File_Type(tarfn);
1130 if (type == 0)
1131 total_size = TWFunc::Get_File_Size(tarfn);
1132 else {
1133 Command = "pigz -l " + tarfn;
1134 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1135 we get the uncompressed size at once. */
1136 TWFunc::Exec_Cmd(Command, result);
1137 if (!result.empty()) {
1138 /* Expected output:
1139 compressed original reduced name
1140 95855838 179403776 -1.3% data.yaffs2.win
1141 ^
1142 split[5]
1143 */
1144 split = TWFunc::split_string(result, ' ', true);
1145 if (split.size() > 4)
1146 total_size = atoi(split[5].c_str());
1147 }
1148 }
1149 LOGINFO("%s's uncompressed size: %llu bytes\n", Tar.c_str(), total_size);
1150
1151 return total_size;
1152}
1153
Dees_Troye34c1332013-02-06 19:13:00 +00001154extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1155 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001156}