blob: 968b6b9e7f7447447c171325071aab62b7c26ab4 [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05003 Copyright 2013 TeamWin
Dees_Troye34c1332013-02-06 19:13:00 +00004 This file is part of TWRP/TeamWin Recovery Project.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05005
Dees_Troye34c1332013-02-06 19:13:00 +00006 TWRP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050010
Dees_Troye34c1332013-02-06 19:13:00 +000011 TWRP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050015
Dees_Troye34c1332013-02-06 19:13:00 +000016 You should have received a copy of the GNU General Public License
17 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050018*/
19
20extern "C" {
21 #include "libtar/libtar.h"
Dees_Troye34c1332013-02-06 19:13:00 +000022 #include "twrpTar.h"
23 #include "tarWrite.h"
Ethan Yonker4b94cfd2014-12-11 10:00:45 -060024 #include "set_metadata.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050025}
26#include <sys/types.h>
27#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050028#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050029#include <string.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050033#include <iostream>
34#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050035#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000036#include <vector>
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 "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050043#include "twrp-functions.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050044#ifndef BUILD_TWRPTAR_MAIN
45#include "data.hpp"
46#include "infomanager.hpp"
47#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050048
49using namespace std;
50
Dees_Troy83bd4832013-05-04 12:39:56 +000051twrpTar::twrpTar(void) {
52 use_encryption = 0;
53 userdata_encryption = 0;
54 use_compression = 0;
55 split_archives = 0;
56 has_data_media = 0;
57 pigz_pid = 0;
58 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000059 Total_Backup_Size = 0;
60 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000061}
62
63twrpTar::~twrpTar(void) {
64 // Do nothing
65}
66
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050067void twrpTar::setfn(string fn) {
68 tarfn = fn;
69}
70
71void twrpTar::setdir(string dir) {
72 tardir = dir;
73}
74
Dees Troye0a433a2013-12-02 04:10:37 +000075void twrpTar::setsize(unsigned long long backup_size) {
76 Total_Backup_Size = backup_size;
77}
78
Ethan Yonker87af5632014-02-10 11:56:35 -060079void twrpTar::setpassword(string pass) {
80 password = pass;
81}
82
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050083int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +000084 int status = 0;
85 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050086 int progress_pipe[2], ret;
87
88 file_count = 0;
89
90 if (pipe(progress_pipe) < 0) {
91 LOGERR("Error creating progress tracking pipe\n");
92 return -1;
93 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050094 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000095 LOGINFO("create tar failed to fork.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050096 close(progress_pipe[0]);
97 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050098 return -1;
99 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500100 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000101 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500102
103 // Child closes input side of progress pipe
104 close(progress_pipe[0]);
105 progress_pipe_fd = progress_pipe[1];
106
Dees_Troy83bd4832013-05-04 12:39:56 +0000107 if (use_encryption || userdata_encryption) {
108 LOGINFO("Using encryption\n");
109 DIR* d;
110 struct dirent* de;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500111 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1, total_size;
Dees_Troy83bd4832013-05-04 12:39:56 +0000112 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
113 int item_len, ret, thread_error = 0;
114 std::vector<TarListStruct> RegularList;
115 std::vector<TarListStruct> EncryptList;
116 string FileName;
117 struct TarListStruct TarItem;
118 twrpTar reg, enc[9];
119 struct stat st;
120 pthread_t enc_thread[9];
121 pthread_attr_t tattr;
122 void *thread_return;
123
124 core_count = sysconf(_SC_NPROCESSORS_CONF);
125 if (core_count > 8)
126 core_count = 8;
127 LOGINFO(" Core Count : %llu\n", core_count);
128 Archive_Current_Size = 0;
129
130 d = opendir(tardir.c_str());
131 if (d == NULL) {
132 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500133 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000134 _exit(-1);
135 }
136 // Figure out the size of all data to be encrypted and create a list of unencrypted files
137 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500138 FileName = tardir + "/" + de->d_name;
139
140 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000141 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500142 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000143 item_len = strlen(de->d_name);
144 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500145 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
146 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000147 LOGERR("Error in Generate_TarList with regular list!\n");
148 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500149 close(progress_pipe_fd);
150 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000151 _exit(-1);
152 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500153 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500154 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000155 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500156 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000157 }
158 } else if (de->d_type == DT_REG) {
159 stat(FileName.c_str(), &st);
160 encrypt_size += (unsigned long long)(st.st_size);
161 }
162 }
163 closedir(d);
164
165 target_size = encrypt_size / core_count;
166 target_size++;
167 LOGINFO(" Unencrypted size: %llu\n", regular_size);
168 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
169 LOGINFO(" Target size : %llu\n", target_size);
170 if (!userdata_encryption) {
171 enc_thread_id = 0;
172 start_thread_id = 0;
173 core_count--;
174 }
175 Archive_Current_Size = 0;
176
177 d = opendir(tardir.c_str());
178 if (d == NULL) {
179 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500180 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000181 _exit(-1);
182 }
183 // Divide up the encrypted file list for threading
184 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500185 FileName = tardir + "/" + de->d_name;
186
187 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000188 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500189 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000190 item_len = strlen(de->d_name);
191 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
192 // Do nothing, we added these to RegularList earlier
193 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500194 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500195 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
196 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000197 LOGERR("Error in Generate_TarList with encrypted list!\n");
198 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500199 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000200 _exit(-1);
201 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500202 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000203 }
204 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
205 stat(FileName.c_str(), &st);
206 if (de->d_type == DT_REG)
207 Archive_Current_Size += (unsigned long long)(st.st_size);
208 TarItem.fn = FileName;
209 TarItem.thread_id = enc_thread_id;
210 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500211 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000212 }
213 }
214 closedir(d);
215 if (enc_thread_id != core_count) {
216 LOGERR("Error dividing up threads for encryption, %i threads for %i cores!\n", enc_thread_id, core_count);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500217 if (enc_thread_id > core_count) {
218 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000219 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500220 } else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000221 LOGERR("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500222 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000223 }
224
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500225 // Send file count to parent
226 write(progress_pipe_fd, &file_count, sizeof(file_count));
227 // Send backup size to parent
228 total_size = regular_size + encrypt_size;
229 write(progress_pipe_fd, &total_size, sizeof(total_size));
230
Dees_Troy83bd4832013-05-04 12:39:56 +0000231 if (userdata_encryption) {
232 // Create a backup of unencrypted data
233 reg.setfn(tarfn);
234 reg.ItemList = &RegularList;
235 reg.thread_id = 0;
236 reg.use_encryption = 0;
237 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000238 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500239 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000240 LOGINFO("Creating unencrypted backup...\n");
241 if (createList((void*)&reg) != 0) {
242 LOGERR("Error creating unencrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500243 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000244 _exit(-1);
245 }
246 }
247
248 if (pthread_attr_init(&tattr)) {
249 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500250 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000251 _exit(-1);
252 }
253 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
254 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500255 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000256 _exit(-1);
257 }
258 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
259 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500260 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000261 _exit(-1);
262 }
263 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
264 LOGERR("Error setting pthread_attr_setstacksize\n");
265 _exit(-1);
266 }*/
267
268 // Create threads for the divided up encryption lists
269 for (i = start_thread_id; i <= core_count; i++) {
270 enc[i].setdir(tardir);
271 enc[i].setfn(tarfn);
272 enc[i].ItemList = &EncryptList;
273 enc[i].thread_id = i;
274 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500275 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000276 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000277 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500278 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000279 LOGINFO("Start encryption thread %i\n", i);
280 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
281 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500282 LOGINFO("Unable to create %i thread for encryption! %i\nContinuing in same thread (backup will be slower).\n", i, ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000283 if (createList((void*)&enc[i]) != 0) {
284 LOGERR("Error creating encrypted backup %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500285 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000286 _exit(-1);
287 } else {
288 enc[i].thread_id = i + 1;
289 }
290 }
291 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
292 }
293 if (pthread_attr_destroy(&tattr)) {
294 LOGERR("Failed to pthread_attr_destroy\n");
295 }
296 for (i = start_thread_id; i <= core_count; i++) {
297 if (enc[i].thread_id == i) {
298 if (pthread_join(enc_thread[i], &thread_return)) {
299 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500300 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000301 _exit(-1);
302 } else {
303 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600304 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000305 if (ret != 0) {
306 thread_error = 1;
307 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500308 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000309 _exit(-1);
310 }
311 }
312 } else {
313 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
314 }
315 }
316 if (thread_error) {
317 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500318 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000319 _exit(-1);
320 }
321 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500322 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000323 _exit(0);
324 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500325 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000326 std::vector<TarListStruct> FileList;
327 unsigned thread_id = 0;
328 unsigned long long target_size = 0;
329 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500330 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000331
332 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500333 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
334 if (ret < 0) {
Dees Troye0a433a2013-12-02 04:10:37 +0000335 LOGERR("Error in Generate_TarList!\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500336 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000337 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000338 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500339 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000340 // Create a backup
341 reg.setfn(tarfn);
342 reg.ItemList = &FileList;
343 reg.thread_id = 0;
344 reg.use_encryption = 0;
345 reg.use_compression = use_compression;
346 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500347 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000348 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
349 gui_print("Breaking backup file into multiple archives...\n");
350 reg.split_archives = 1;
351 } else {
352 reg.split_archives = 0;
353 }
354 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500355 write(progress_pipe_fd, &file_count, sizeof(file_count));
356 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000357 if (createList((void*)&reg) != 0) {
358 LOGERR("Error creating backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500359 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000360 _exit(-1);
361 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500362 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000363 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000364 }
365 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500366 // Parent side
367 unsigned long long fs, size_backup, files_backup, total_backup_size;
368 int first_data = 0;
369 double display_percent, progress_percent;
370 char file_progress[1024];
371 char size_progress[1024];
372 files_backup = 0;
373 size_backup = 0;
374
375 // Parent closes output side
376 close(progress_pipe[1]);
377
378 // Read progress data from children
379 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
380 if (first_data == 0) {
381 // First incoming data is the file count
382 file_count = fs;
383 if (file_count == 0) file_count = 1; // prevent division by 0 below
384 first_data = 1;
385 } else if (first_data == 1) {
386 // Second incoming data is total size
387 total_backup_size = fs;
388 first_data = 2;
389 } else {
390 files_backup++;
391 size_backup += fs;
392 display_percent = (double)(files_backup) / (double)(file_count) * 100;
393 sprintf(file_progress, "%llu of %llu files, %i%%", files_backup, file_count, (int)(display_percent));
394#ifndef BUILD_TWRPTAR_MAIN
395 DataManager::SetValue("tw_file_progress", file_progress);
396 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
397 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
398 DataManager::SetValue("tw_size_progress", size_progress);
399 progress_percent = (display_percent / 100);
400 DataManager::SetProgress((float)(progress_percent));
401#endif //ndef BUILD_TWRPTAR_MAIN
402 }
403 }
404 close(progress_pipe[0]);
405#ifndef BUILD_TWRPTAR_MAIN
406 DataManager::SetValue("tw_file_progress", "");
407 DataManager::SetValue("tw_size_progress", "");
408
409 InfoManager backup_info(backup_folder + partition_name + ".info");
410 backup_info.SetValue("backup_size", size_backup);
411 if (use_compression && use_encryption)
412 backup_info.SetValue("backup_type", 3);
413 else if (use_encryption)
414 backup_info.SetValue("backup_type", 2);
415 else if (use_compression)
416 backup_info.SetValue("backup_type", 1);
417 else
418 backup_info.SetValue("backup_type", 0);
419 backup_info.SetValue("file_count", files_backup);
420 backup_info.SaveValues();
421#endif //ndef BUILD_TWRPTAR_MAIN
Dees_Troy83bd4832013-05-04 12:39:56 +0000422 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500423 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500424 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500425 return 0;
426}
427
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500428int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000429 int status = 0;
430 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500431 int progress_pipe[2], ret;
432
433 if (pipe(progress_pipe) < 0) {
434 LOGERR("Error creating progress tracking pipe\n");
435 return -1;
436 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000437
438 pid = fork();
439 if (pid >= 0) // fork was successful
440 {
441 if (pid == 0) // child process
442 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500443 close(progress_pipe[0]);
444 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000445 if (TWFunc::Path_Exists(tarfn)) {
446 LOGINFO("Single archive\n");
447 if (extract() != 0)
448 _exit(-1);
449 else
450 _exit(0);
451 } else {
452 LOGINFO("Multiple archives\n");
453 string temp;
454 char actual_filename[255];
455 twrpTar tars[9];
456 pthread_t tar_thread[9];
457 pthread_attr_t tattr;
458 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
459 void *thread_return;
460
461 basefn = tarfn;
462 temp = basefn + "%i%02i";
463 tarfn += "000";
464 if (!TWFunc::Path_Exists(tarfn)) {
465 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500466 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000467 _exit(-1);
468 }
469 if (TWFunc::Get_File_Type(tarfn) != 2) {
470 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
471 tars[0].basefn = basefn;
472 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500473 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000474 if (extractMulti((void*)&tars[0]) != 0) {
475 LOGERR("Error extracting split archive.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500476 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000477 _exit(-1);
478 }
479 } else {
480 start_thread_id = 0;
481 }
482 // Start threading encrypted restores
483 if (pthread_attr_init(&tattr)) {
484 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500485 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000486 _exit(-1);
487 }
488 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
489 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500490 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000491 _exit(-1);
492 }
493 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
494 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500495 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000496 _exit(-1);
497 }
498 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
499 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500500 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000501 _exit(-1);
502 }*/
503 for (i = start_thread_id; i < 9; i++) {
504 sprintf(actual_filename, temp.c_str(), i, 0);
505 if (TWFunc::Path_Exists(actual_filename)) {
506 thread_count++;
507 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500508 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000509 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500510 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000511 LOGINFO("Creating extract thread ID %i\n", i);
512 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
513 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500514 LOGINFO("Unable to create %i thread for extraction! %i\nContinuing in same thread (restore will be slower).\n", i, ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000515 if (extractMulti((void*)&tars[i]) != 0) {
516 LOGERR("Error extracting backup in thread %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500517 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000518 _exit(-1);
519 } else {
520 tars[i].thread_id = i + 1;
521 }
522 }
523 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
524 } else {
525 break;
526 }
527 }
528 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
529 if (tars[i].thread_id == i) {
530 if (pthread_join(tar_thread[i], &thread_return)) {
531 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500532 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000533 _exit(-1);
534 } else {
535 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600536 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000537 if (ret != 0) {
538 thread_error = 1;
539 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500540 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000541 _exit(-1);
542 }
543 }
544 } else {
545 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
546 }
547 }
548 if (thread_error) {
549 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500550 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000551 _exit(-1);
552 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500553 LOGINFO("Finished encrypted restore.\n");
554 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000555 _exit(0);
556 }
557 }
558 else // parent process
559 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500560 unsigned long long fs, size_backup;
561 double display_percent, progress_percent;
562 char size_progress[1024];
563 size_backup = 0;
564
565 // Parent closes output side
566 close(progress_pipe[1]);
567
568 // Read progress data from children
569 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
570 size_backup += fs;
571 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
572 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
573 progress_percent = (display_percent / 100);
574#ifndef BUILD_TWRPTAR_MAIN
575 DataManager::SetValue("tw_size_progress", size_progress);
576 DataManager::SetProgress((float)(progress_percent));
577#endif //ndef BUILD_TWRPTAR_MAIN
578 }
579 close(progress_pipe[0]);
580#ifndef BUILD_TWRPTAR_MAIN
581 DataManager::SetValue("tw_file_progress", "");
582#endif //ndef BUILD_TWRPTAR_MAIN
583 *other_backups_size += size_backup;
584
Dees_Troy83bd4832013-05-04 12:39:56 +0000585 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
586 return -1;
587 }
588 }
589 else // fork has failed
590 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500591 close(progress_pipe[0]);
592 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000593 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500594 return -1;
595 }
596 return 0;
597}
598
Dees_Troy83bd4832013-05-04 12:39:56 +0000599int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
600 DIR* d;
601 struct dirent* de;
602 struct stat st;
603 string FileName;
604 struct TarListStruct TarItem;
605 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500606 int ret, file_count;
607 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000608
Dees_Troy83bd4832013-05-04 12:39:56 +0000609 d = opendir(Path.c_str());
610 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000611 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000612 closedir(d);
613 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500614 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000615 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500616 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500617
Matt Mower50248ab2014-03-31 15:58:40 -0500618 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000619 continue;
620 TarItem.fn = FileName;
621 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500622 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000623 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500624 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
625 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500626 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500627 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000628 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
629 stat(FileName.c_str(), &st);
630 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500631 if (de->d_type == DT_REG) {
632 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000633 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500634 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000635 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
636 *thread_id = *thread_id + 1;
637 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500638 }
639 }
640 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000641 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500642 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500643}
644
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500645int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000646 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000647 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500648 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500649 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000650 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500651 return -1;
652 }
653 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000654 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500655 return -1;
656 }
657 return 0;
658}
659
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500660int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000661 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200662
663 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500664 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000665 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000666 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500667 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000668 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600669 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000670 if (ret < 1) {
671 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
672 return -1;
673 }
674 if (ret == 1) {
675 LOGERR("Decrypted file is not in tar format.\n");
676 return -1;
677 }
678 if (ret == 3) {
679 LOGINFO("Extracting encrypted and compressed tar.\n");
680 Archive_Current_Type = 3;
681 } else
682 LOGINFO("Extracting encrypted tar.\n");
683 return extractTar();
684 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000685 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500686 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500687 }
688}
689
Dees Troye0a433a2013-12-02 04:10:37 +0000690int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000691 struct stat st;
692 char buf[PATH_MAX];
693 int list_size = TarList->size(), i = 0, archive_count = 0;
694 string temp;
695 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000696 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500697 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000698
Dees Troye0a433a2013-12-02 04:10:37 +0000699 if (split_archives) {
700 basefn = tarfn;
701 temp = basefn + "%i%02i";
702 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
703 tarfn = actual_filename;
704 include_root_dir = true;
705 } else {
706 include_root_dir = false;
707 }
708 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000709 if (createTar() != 0) {
710 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
711 return -2;
712 }
713 Archive_Current_Size = 0;
714
715 while (i < list_size) {
716 if (TarList->at(i).thread_id == thread_id) {
717 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400718 lstat(buf, &st);
719 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500720 fs = (unsigned long long)(st.st_size);
721 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000722 if (closeTar() != 0) {
723 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
724 return -3;
725 }
726 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000727 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000728 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000729 LOGERR("Too many archives for thread %i\n", thread_id);
730 return -4;
731 }
732 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
733 tarfn = actual_filename;
734 if (createTar() != 0) {
735 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
736 return -2;
737 }
738 Archive_Current_Size = 0;
739 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500740 Archive_Current_Size += fs;
741 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000742 }
Dees Troye0a433a2013-12-02 04:10:37 +0000743 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
744 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000745 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
746 return -1;
747 }
748 }
749 i++;
750 }
751 if (closeTar() != 0) {
752 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
753 return -3;
754 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600755 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000756 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500757}
758
Dees_Troy83bd4832013-05-04 12:39:56 +0000759void* twrpTar::createList(void *cookie) {
760
761 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600762 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000763 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
764 return (void*)-2;
765 }
766 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
767 return (void*)0;
768}
769
770void* twrpTar::extractMulti(void *cookie) {
771
772 twrpTar* threadTar = (twrpTar*) cookie;
773 int archive_count = 0;
774 string temp = threadTar->basefn + "%i%02i";
775 char actual_filename[255];
776 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
777 while (TWFunc::Path_Exists(actual_filename)) {
778 threadTar->tarfn = actual_filename;
779 if (threadTar->extract() != 0) {
780 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
781 return (void*)-2;
782 }
783 archive_count++;
784 if (archive_count > 99)
785 break;
786 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
787 }
788 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
789 return (void*)0;
790}
791
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500792int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
793 char* charTarFile = (char*) fn.c_str();
794
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200795 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 -0500796 return -1;
797 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200798 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 -0500799 return -1;
800 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500801 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500802 if (tar_append_file(t, file, file) == -1)
803 return -1;
804 }
805 if (tar_append_eof(t) == -1)
806 return -1;
807 if (tar_close(t) == -1)
808 return -1;
809 return 0;
810}
811
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500812int twrpTar::createTar() {
813 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000814 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000815 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500816
Dees_Troy83bd4832013-05-04 12:39:56 +0000817 if (use_encryption && use_compression) {
818 // Compressed and encrypted
819 Archive_Current_Type = 3;
820 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000821 int i, pipes[4];
822
823 if (pipe(pipes) < 0) {
824 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500825 return -1;
826 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000827 if (pipe(pipes + 2) < 0) {
828 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500829 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 }
Dees Troy9d723272014-04-07 17:13:10 +0000831 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);
832 if (output_fd < 0) {
833 LOGERR("Failed to open '%s'\n", tarfn.c_str());
834 for (i = 0; i < 4; i++)
835 close(pipes[i]); // close all
836 return -1;
837 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000838 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400839
Dees_Troy83bd4832013-05-04 12:39:56 +0000840 if (pigz_pid < 0) {
841 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000842 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000843 for (i = 0; i < 4; i++)
844 close(pipes[i]); // close all
845 return -1;
846 } else if (pigz_pid == 0) {
847 // pigz Child
848 close(pipes[1]);
849 close(pipes[2]);
850 close(0);
851 dup2(pipes[0], 0);
852 close(1);
853 dup2(pipes[3], 1);
854 if (execlp("pigz", "pigz", "-", NULL) < 0) {
855 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000856 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000857 close(pipes[0]);
858 close(pipes[3]);
859 _exit(-1);
860 }
861 } else {
862 // Parent
863 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400864
Dees_Troy83bd4832013-05-04 12:39:56 +0000865 if (oaes_pid < 0) {
866 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000867 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000868 for (i = 0; i < 4; i++)
869 close(pipes[i]); // close all
870 return -1;
871 } else if (oaes_pid == 0) {
872 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000873 close(pipes[0]);
874 close(pipes[1]);
875 close(pipes[3]);
876 close(0);
877 dup2(pipes[2], 0);
878 close(1);
879 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600880 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000881 LOGERR("execlp openaes ERROR!\n");
882 close(pipes[2]);
883 close(output_fd);
884 _exit(-1);
885 }
886 } else {
887 // Parent
888 close(pipes[0]);
889 close(pipes[2]);
890 close(pipes[3]);
891 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200892 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 +0000893 close(fd);
894 LOGERR("tar_fdopen failed\n");
895 return -1;
896 }
897 return 0;
898 }
899 }
900 } else if (use_compression) {
901 // Compressed
902 Archive_Current_Type = 1;
903 LOGINFO("Using compression...\n");
904 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000905 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);
906 if (output_fd < 0) {
907 LOGERR("Failed to open '%s'\n", tarfn.c_str());
908 close(pigzfd[0]);
909 return -1;
910 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000911
912 if (pipe(pigzfd) < 0) {
913 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000914 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000915 return -1;
916 }
917 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400918
Dees_Troy83bd4832013-05-04 12:39:56 +0000919 if (pigz_pid < 0) {
920 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000921 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000922 close(pigzfd[0]);
923 close(pigzfd[1]);
924 return -1;
925 } else if (pigz_pid == 0) {
926 // Child
927 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000928 dup2(pigzfd[0], 0); // remap stdin
929 dup2(output_fd, 1); // remap stdout to output file
930 if (execlp("pigz", "pigz", "-", NULL) < 0) {
931 LOGERR("execlp pigz ERROR!\n");
932 close(output_fd);
933 close(pigzfd[0]);
934 _exit(-1);
935 }
936 } else {
937 // Parent
938 close(pigzfd[0]); // close parent input
939 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200940 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 +0000941 close(fd);
942 LOGERR("tar_fdopen failed\n");
943 return -1;
944 }
945 }
946 } else if (use_encryption) {
947 // Encrypted
948 Archive_Current_Type = 2;
949 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000950 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000951 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);
952 if (output_fd < 0) {
953 LOGERR("Failed to open '%s'\n", tarfn.c_str());
954 return -1;
955 }
956 if (pipe(oaesfd) < 0) {
957 LOGERR("Error creating pipe\n");
958 close(output_fd);
959 return -1;
960 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000961 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400962
Dees_Troy83bd4832013-05-04 12:39:56 +0000963 if (oaes_pid < 0) {
964 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000965 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000966 close(oaesfd[0]);
967 close(oaesfd[1]);
968 return -1;
969 } else if (oaes_pid == 0) {
970 // Child
971 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000972 dup2(oaesfd[0], 0); // remap stdin
973 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600974 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000975 LOGERR("execlp openaes ERROR!\n");
976 close(output_fd);
977 close(oaesfd[0]);
978 _exit(-1);
979 }
980 } else {
981 // Parent
982 close(oaesfd[0]); // close parent input
983 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200984 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 +0000985 close(fd);
986 LOGERR("tar_fdopen failed\n");
987 return -1;
988 }
989 return 0;
990 }
991 } else {
992 // Not compressed or encrypted
993 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200994 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 +0000995 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
996 return -1;
997 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500998 }
999 return 0;
1000}
1001
Dees_Troy83bd4832013-05-04 12:39:56 +00001002int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001003 char* charRootDir = (char*) tardir.c_str();
1004 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001005 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001006
Dees_Troy83bd4832013-05-04 12:39:56 +00001007 if (Archive_Current_Type == 3) {
1008 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001009 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001010 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1011 if (input_fd < 0) {
1012 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1013 return -1;
1014 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001015
1016 if (pipe(pipes) < 0) {
1017 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001018 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001019 return -1;
1020 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001021 if (pipe(pipes + 2) < 0) {
1022 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001023 close(pipes[0]);
1024 close(pipes[1]);
1025 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001026 return -1;
1027 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001028 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001029
Dees_Troy83bd4832013-05-04 12:39:56 +00001030 if (oaes_pid < 0) {
1031 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001032 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001033 for (i = 0; i < 4; i++)
1034 close(pipes[i]); // close all
1035 return -1;
1036 } else if (oaes_pid == 0) {
1037 // openaes Child
1038 close(pipes[0]); // Close pipes that are not used by this child
1039 close(pipes[2]);
1040 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001041 close(0);
1042 dup2(input_fd, 0);
1043 close(1);
1044 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001045 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001046 LOGERR("execlp openaes ERROR!\n");
1047 close(input_fd);
1048 close(pipes[1]);
1049 _exit(-1);
1050 }
1051 } else {
1052 // Parent
1053 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001054
Dees_Troy83bd4832013-05-04 12:39:56 +00001055 if (pigz_pid < 0) {
1056 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001057 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001058 for (i = 0; i < 4; i++)
1059 close(pipes[i]); // close all
1060 return -1;
1061 } else if (pigz_pid == 0) {
1062 // pigz Child
1063 close(pipes[1]); // Close pipes not used by this child
1064 close(pipes[2]);
1065 close(0);
1066 dup2(pipes[0], 0);
1067 close(1);
1068 dup2(pipes[3], 1);
1069 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1070 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +00001071 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001072 close(pipes[0]);
1073 close(pipes[3]);
1074 _exit(-1);
1075 }
1076 } else {
1077 // Parent
1078 close(pipes[0]); // Close pipes not used by parent
1079 close(pipes[1]);
1080 close(pipes[3]);
1081 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001082 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 +00001083 close(fd);
1084 LOGERR("tar_fdopen failed\n");
1085 return -1;
1086 }
1087 }
1088 }
1089 } else if (Archive_Current_Type == 2) {
1090 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001091 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001092 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1093 if (input_fd < 0) {
1094 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1095 return -1;
1096 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001097
Dees Troy9d723272014-04-07 17:13:10 +00001098 if (pipe(oaesfd) < 0) {
1099 LOGERR("Error creating pipe\n");
1100 close(input_fd);
1101 return -1;
1102 }
1103
Dees_Troy83bd4832013-05-04 12:39:56 +00001104 oaes_pid = fork();
1105 if (oaes_pid < 0) {
1106 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001107 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001108 close(oaesfd[0]);
1109 close(oaesfd[1]);
1110 return -1;
1111 } else if (oaes_pid == 0) {
1112 // Child
1113 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001114 close(0); // close stdin
1115 dup2(oaesfd[1], 1); // remap stdout
1116 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001117 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001118 LOGERR("execlp openaes ERROR!\n");
1119 close(input_fd);
1120 close(oaesfd[1]);
1121 _exit(-1);
1122 }
1123 } else {
1124 // Parent
1125 close(oaesfd[1]); // close parent output
1126 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001127 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 +00001128 close(fd);
1129 LOGERR("tar_fdopen failed\n");
1130 return -1;
1131 }
1132 }
1133 } else if (Archive_Current_Type == 1) {
1134 LOGINFO("Opening as a gzip...\n");
1135 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001136 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1137 if (input_fd < 0) {
1138 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1139 return -1;
1140 }
1141 if (pipe(pigzfd) < 0) {
1142 LOGERR("Error creating pipe\n");
1143 close(input_fd);
1144 return -1;
1145 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001146
1147 pigz_pid = fork();
1148 if (pigz_pid < 0) {
1149 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001150 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001151 close(pigzfd[0]);
1152 close(pigzfd[1]);
1153 return -1;
1154 } else if (pigz_pid == 0) {
1155 // Child
1156 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001157 dup2(input_fd, 0); // remap input fd to stdin
1158 dup2(pigzfd[1], 1); // remap stdout
1159 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1160 close(pigzfd[1]);
1161 close(input_fd);
1162 LOGERR("execlp openaes ERROR!\n");
1163 _exit(-1);
1164 }
1165 } else {
1166 // Parent
1167 close(pigzfd[1]); // close parent output
1168 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001169 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 +00001170 close(fd);
1171 LOGERR("tar_fdopen failed\n");
1172 return -1;
1173 }
1174 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001175 } 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 +00001176 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1177 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001178 }
1179 return 0;
1180}
1181
1182string twrpTar::Strip_Root_Dir(string Path) {
1183 string temp;
1184 size_t slash;
1185
1186 if (Path.substr(0, 1) == "/")
1187 temp = Path.substr(1, Path.size() - 1);
1188 else
1189 temp = Path;
1190 slash = temp.find("/");
1191 if (slash == string::npos)
1192 return temp;
1193 else {
1194 string stripped;
1195
1196 stripped = temp.substr(slash, temp.size() - slash);
1197 return stripped;
1198 }
1199 return temp;
1200}
1201
1202int twrpTar::addFile(string fn, bool include_root) {
1203 char* charTarFile = (char*) fn.c_str();
1204 if (include_root) {
1205 if (tar_append_file(t, charTarFile, NULL) == -1)
1206 return -1;
1207 } else {
1208 string temp = Strip_Root_Dir(fn);
1209 char* charTarPath = (char*) temp.c_str();
1210 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1211 return -1;
1212 }
1213 return 0;
1214}
1215
Dees_Troy83bd4832013-05-04 12:39:56 +00001216int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001217 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001218 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001219 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001220 tar_close(t);
1221 return -1;
1222 }
1223 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001224 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001225 return -1;
1226 }
Dees_Troy2727b992013-08-14 20:09:30 +00001227 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001228 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001229 int status;
1230 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1231 return -1;
1232 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1233 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001234 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001235 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001236 if (use_compression && !use_encryption) {
1237 string gzname = tarfn + ".gz";
1238 if (TWFunc::Path_Exists(gzname)) {
1239 rename(gzname.c_str(), tarfn.c_str());
1240 }
1241 }
1242 if (TWFunc::Get_File_Size(tarfn) == 0) {
1243 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1244 return -1;
1245 }
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06001246 tw_set_default_metadata(tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001247 return 0;
1248}
1249
1250int twrpTar::removeEOT(string tarFile) {
1251 char* charTarFile = (char*) tarFile.c_str();
1252 off_t tarFileEnd;
1253 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001254 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001255 tar_skip_regfile(t);
1256 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001257 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001258 if (tar_close(t) == -1)
1259 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001260 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001261 return -1;
1262 return 0;
1263}
1264
n0d33b511632013-03-06 21:14:15 +02001265int twrpTar::entryExists(string entry) {
1266 char* searchstr = (char*)entry.c_str();
1267 int ret;
1268
Dees_Troy83bd4832013-05-04 12:39:56 +00001269 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001270
Dees_Troy83bd4832013-05-04 12:39:56 +00001271 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001272 ret = 0;
1273 else
1274 ret = tar_find(t, searchstr);
1275
Dees_Troy83bd4832013-05-04 12:39:56 +00001276 if (closeTar() != 0)
1277 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001278
1279 return ret;
1280}
1281
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001282unsigned long long twrpTar::get_size() {
1283 if (TWFunc::Path_Exists(tarfn)) {
1284 LOGINFO("Single archive\n");
1285 int type = 0;
1286 return uncompressedSize(tarfn, &type);
1287 } else {
1288 LOGINFO("Multiple archives\n");
1289 string temp;
1290 char actual_filename[255];
1291 int archive_count = 0, i, type = 0, temp_type = 0;
1292 unsigned long long total_restore_size = 0;
1293
1294 basefn = tarfn;
1295 temp = basefn + "%i%02i";
1296 tarfn += "000";
1297 thread_id = 0;
1298 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1299 if (!TWFunc::Path_Exists(actual_filename)) {
1300 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1301 return 0;
1302 }
1303 for (i = 0; i < 9; i++) {
1304 archive_count = 0;
1305 sprintf(actual_filename, temp.c_str(), i, archive_count);
1306 while (TWFunc::Path_Exists(actual_filename)) {
1307 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1308 if (temp_type > type)
1309 type = temp_type;
1310 archive_count++;
1311 if (archive_count > 99)
1312 break;
1313 sprintf(actual_filename, temp.c_str(), i, archive_count);
1314 }
1315 }
1316#ifndef BUILD_TWRPTAR_MAIN
1317 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1318 backup_info.SetValue("backup_size", total_restore_size);
1319 backup_info.SetValue("backup_type", type);
1320 backup_info.SaveValues();
1321#endif //ndef BUILD_TWRPTAR_MAIN
1322 return total_restore_size;
1323 }
1324 return 0;
1325}
1326
1327unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1328 int type = 0;
1329 unsigned long long total_size = 0;
1330 string Tar, Command, result;
1331 vector<string> split;
1332
1333 Tar = TWFunc::Get_Filename(filename);
1334 type = TWFunc::Get_File_Type(filename);
1335 if (type == 0) {
1336 total_size = TWFunc::Get_File_Size(filename);
1337 *archive_type = 0;
1338 } else if (type == 1) {
1339 // Compressed
1340 Command = "pigz -l '" + filename + "'";
1341 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1342 we get the uncompressed size at once. */
1343 TWFunc::Exec_Cmd(Command, result);
1344 if (!result.empty()) {
1345 /* Expected output:
1346 compressed original reduced name
1347 95855838 179403776 -1.3% data.yaffs2.win
1348 ^
1349 split[5]
1350 */
1351 split = TWFunc::split_string(result, ' ', true);
1352 if (split.size() > 4)
1353 total_size = atoi(split[5].c_str());
1354 }
1355 *archive_type = 1;
1356 } else if (type == 2) {
1357 // File is encrypted and may be compressed
1358 int ret = TWFunc::Try_Decrypting_File(filename, password);
1359 *archive_type = 2;
1360 if (ret < 1) {
1361 LOGERR("Failed to decrypt tar file '%s'\n", filename.c_str());
1362 total_size = TWFunc::Get_File_Size(filename);
1363 } else if (ret == 1) {
1364 LOGERR("Decrypted file is not in tar format.\n");
1365 total_size = TWFunc::Get_File_Size(filename);
1366 } else if (ret == 3) {
1367 *archive_type = 3;
1368 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1369 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1370 we get the uncompressed size at once. */
1371 TWFunc::Exec_Cmd(Command, result);
1372 if (!result.empty()) {
1373 LOGINFO("result was: '%s'\n", result.c_str());
1374 /* Expected output:
1375 compressed original reduced name
1376 95855838 179403776 -1.3% data.yaffs2.win
1377 ^
1378 split[5]
1379 */
1380 split = TWFunc::split_string(result, ' ', true);
1381 if (split.size() > 4)
1382 total_size = atoi(split[5].c_str());
1383 }
1384 } else {
1385 total_size = TWFunc::Get_File_Size(filename);
1386 }
1387 }
1388
1389 return total_size;
1390}
1391
Dees_Troye34c1332013-02-06 19:13:00 +00001392extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1393 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001394}