blob: b5d66d31b1f46d48f0b2ce33bcf6879f52df4ae6 [file] [log] [blame]
Dees Troye0a433a2013-12-02 04:10:37 +00001
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002/*
bigbiff bigbiff34684ff2013-12-01 21:03:45 -05003 Copyright 2013 TeamWin
Dees_Troye34c1332013-02-06 19:13:00 +00004 This file is part of TWRP/TeamWin Recovery Project.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05005
Dees_Troye34c1332013-02-06 19:13:00 +00006 TWRP is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050010
Dees_Troye34c1332013-02-06 19:13:00 +000011 TWRP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050015
Dees_Troye34c1332013-02-06 19:13:00 +000016 You should have received a copy of the GNU General Public License
17 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050018*/
19
20extern "C" {
21 #include "libtar/libtar.h"
Dees_Troye34c1332013-02-06 19:13:00 +000022 #include "twrpTar.h"
23 #include "tarWrite.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050024}
25#include <sys/types.h>
26#include <sys/stat.h>
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050027#include <sys/wait.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050028#include <string.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <fstream>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050032#include <iostream>
33#include <string>
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050034#include <sstream>
Dees_Troy83bd4832013-05-04 12:39:56 +000035#include <vector>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050036#include <dirent.h>
bigbiff bigbiffc49d7062013-10-11 20:28:00 -040037#include <libgen.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050038#include <sys/mman.h>
39#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050041#include "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050042#include "twrp-functions.hpp"
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050043#ifndef BUILD_TWRPTAR_MAIN
44#include "data.hpp"
45#include "infomanager.hpp"
46#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050047
48using namespace std;
49
Dees_Troy83bd4832013-05-04 12:39:56 +000050twrpTar::twrpTar(void) {
51 use_encryption = 0;
52 userdata_encryption = 0;
53 use_compression = 0;
54 split_archives = 0;
55 has_data_media = 0;
56 pigz_pid = 0;
57 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000058 Total_Backup_Size = 0;
59 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000060}
61
62twrpTar::~twrpTar(void) {
63 // Do nothing
64}
65
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050066void twrpTar::setfn(string fn) {
67 tarfn = fn;
68}
69
70void twrpTar::setdir(string dir) {
71 tardir = dir;
72}
73
Dees Troye0a433a2013-12-02 04:10:37 +000074void twrpTar::setsize(unsigned long long backup_size) {
75 Total_Backup_Size = backup_size;
76}
77
Ethan Yonker87af5632014-02-10 11:56:35 -060078void twrpTar::setpassword(string pass) {
79 password = pass;
80}
81
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050082int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +000083 int status = 0;
84 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050085 int progress_pipe[2], ret;
86
87 file_count = 0;
88
89 if (pipe(progress_pipe) < 0) {
90 LOGERR("Error creating progress tracking pipe\n");
91 return -1;
92 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050093 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000094 LOGINFO("create tar failed to fork.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050095 close(progress_pipe[0]);
96 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050097 return -1;
98 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050099 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000100 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500101
102 // Child closes input side of progress pipe
103 close(progress_pipe[0]);
104 progress_pipe_fd = progress_pipe[1];
105
Dees_Troy83bd4832013-05-04 12:39:56 +0000106 if (use_encryption || userdata_encryption) {
107 LOGINFO("Using encryption\n");
108 DIR* d;
109 struct dirent* de;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500110 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1, total_size;
Dees_Troy83bd4832013-05-04 12:39:56 +0000111 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
112 int item_len, ret, thread_error = 0;
113 std::vector<TarListStruct> RegularList;
114 std::vector<TarListStruct> EncryptList;
115 string FileName;
116 struct TarListStruct TarItem;
117 twrpTar reg, enc[9];
118 struct stat st;
119 pthread_t enc_thread[9];
120 pthread_attr_t tattr;
121 void *thread_return;
122
123 core_count = sysconf(_SC_NPROCESSORS_CONF);
124 if (core_count > 8)
125 core_count = 8;
126 LOGINFO(" Core Count : %llu\n", core_count);
127 Archive_Current_Size = 0;
128
129 d = opendir(tardir.c_str());
130 if (d == NULL) {
131 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500132 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000133 _exit(-1);
134 }
135 // Figure out the size of all data to be encrypted and create a list of unencrypted files
136 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500137 FileName = tardir + "/" + de->d_name;
138
139 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000140 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500141 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000142 item_len = strlen(de->d_name);
143 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 -0500144 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
145 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000146 LOGERR("Error in Generate_TarList with regular list!\n");
147 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500148 close(progress_pipe_fd);
149 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000150 _exit(-1);
151 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500152 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500153 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000154 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500155 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000156 }
157 } else if (de->d_type == DT_REG) {
158 stat(FileName.c_str(), &st);
159 encrypt_size += (unsigned long long)(st.st_size);
160 }
161 }
162 closedir(d);
163
164 target_size = encrypt_size / core_count;
165 target_size++;
166 LOGINFO(" Unencrypted size: %llu\n", regular_size);
167 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
168 LOGINFO(" Target size : %llu\n", target_size);
169 if (!userdata_encryption) {
170 enc_thread_id = 0;
171 start_thread_id = 0;
172 core_count--;
173 }
174 Archive_Current_Size = 0;
175
176 d = opendir(tardir.c_str());
177 if (d == NULL) {
178 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500179 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000180 _exit(-1);
181 }
182 // Divide up the encrypted file list for threading
183 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500184 FileName = tardir + "/" + de->d_name;
185
186 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000187 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500188 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000189 item_len = strlen(de->d_name);
190 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
191 // Do nothing, we added these to RegularList earlier
192 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500193 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500194 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
195 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000196 LOGERR("Error in Generate_TarList with encrypted list!\n");
197 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500198 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000199 _exit(-1);
200 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500201 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000202 }
203 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
204 stat(FileName.c_str(), &st);
205 if (de->d_type == DT_REG)
206 Archive_Current_Size += (unsigned long long)(st.st_size);
207 TarItem.fn = FileName;
208 TarItem.thread_id = enc_thread_id;
209 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500210 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000211 }
212 }
213 closedir(d);
214 if (enc_thread_id != core_count) {
215 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 -0500216 if (enc_thread_id > core_count) {
217 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000218 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500219 } else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000220 LOGERR("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500221 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000222 }
223
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500224 // Send file count to parent
225 write(progress_pipe_fd, &file_count, sizeof(file_count));
226 // Send backup size to parent
227 total_size = regular_size + encrypt_size;
228 write(progress_pipe_fd, &total_size, sizeof(total_size));
229
Dees_Troy83bd4832013-05-04 12:39:56 +0000230 if (userdata_encryption) {
231 // Create a backup of unencrypted data
232 reg.setfn(tarfn);
233 reg.ItemList = &RegularList;
234 reg.thread_id = 0;
235 reg.use_encryption = 0;
236 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000237 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500238 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000239 LOGINFO("Creating unencrypted backup...\n");
240 if (createList((void*)&reg) != 0) {
241 LOGERR("Error creating unencrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 _exit(-1);
244 }
245 }
246
247 if (pthread_attr_init(&tattr)) {
248 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500249 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000250 _exit(-1);
251 }
252 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
253 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500254 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000255 _exit(-1);
256 }
257 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
258 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500259 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000260 _exit(-1);
261 }
262 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
263 LOGERR("Error setting pthread_attr_setstacksize\n");
264 _exit(-1);
265 }*/
266
267 // Create threads for the divided up encryption lists
268 for (i = start_thread_id; i <= core_count; i++) {
269 enc[i].setdir(tardir);
270 enc[i].setfn(tarfn);
271 enc[i].ItemList = &EncryptList;
272 enc[i].thread_id = i;
273 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500274 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000275 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000276 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500277 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000278 LOGINFO("Start encryption thread %i\n", i);
279 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
280 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500281 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 +0000282 if (createList((void*)&enc[i]) != 0) {
283 LOGERR("Error creating encrypted backup %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500284 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000285 _exit(-1);
286 } else {
287 enc[i].thread_id = i + 1;
288 }
289 }
290 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
291 }
292 if (pthread_attr_destroy(&tattr)) {
293 LOGERR("Failed to pthread_attr_destroy\n");
294 }
295 for (i = start_thread_id; i <= core_count; i++) {
296 if (enc[i].thread_id == i) {
297 if (pthread_join(enc_thread[i], &thread_return)) {
298 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500299 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000300 _exit(-1);
301 } else {
302 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600303 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000304 if (ret != 0) {
305 thread_error = 1;
306 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500307 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000308 _exit(-1);
309 }
310 }
311 } else {
312 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
313 }
314 }
315 if (thread_error) {
316 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500317 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000318 _exit(-1);
319 }
320 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500321 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000322 _exit(0);
323 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500324 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000325 std::vector<TarListStruct> FileList;
326 unsigned thread_id = 0;
327 unsigned long long target_size = 0;
328 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500329 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000330
331 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500332 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
333 if (ret < 0) {
Dees Troye0a433a2013-12-02 04:10:37 +0000334 LOGERR("Error in Generate_TarList!\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500335 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000336 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000337 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500338 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000339 // Create a backup
340 reg.setfn(tarfn);
341 reg.ItemList = &FileList;
342 reg.thread_id = 0;
343 reg.use_encryption = 0;
344 reg.use_compression = use_compression;
345 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500346 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000347 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
348 gui_print("Breaking backup file into multiple archives...\n");
349 reg.split_archives = 1;
350 } else {
351 reg.split_archives = 0;
352 }
353 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500354 write(progress_pipe_fd, &file_count, sizeof(file_count));
355 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000356 if (createList((void*)&reg) != 0) {
357 LOGERR("Error creating backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500358 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000359 _exit(-1);
360 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500361 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000362 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000363 }
364 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500365 // Parent side
366 unsigned long long fs, size_backup, files_backup, total_backup_size;
367 int first_data = 0;
368 double display_percent, progress_percent;
369 char file_progress[1024];
370 char size_progress[1024];
371 files_backup = 0;
372 size_backup = 0;
373
374 // Parent closes output side
375 close(progress_pipe[1]);
376
377 // Read progress data from children
378 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
379 if (first_data == 0) {
380 // First incoming data is the file count
381 file_count = fs;
382 if (file_count == 0) file_count = 1; // prevent division by 0 below
383 first_data = 1;
384 } else if (first_data == 1) {
385 // Second incoming data is total size
386 total_backup_size = fs;
387 first_data = 2;
388 } else {
389 files_backup++;
390 size_backup += fs;
391 display_percent = (double)(files_backup) / (double)(file_count) * 100;
392 sprintf(file_progress, "%llu of %llu files, %i%%", files_backup, file_count, (int)(display_percent));
393#ifndef BUILD_TWRPTAR_MAIN
394 DataManager::SetValue("tw_file_progress", file_progress);
395 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
396 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
397 DataManager::SetValue("tw_size_progress", size_progress);
398 progress_percent = (display_percent / 100);
399 DataManager::SetProgress((float)(progress_percent));
400#endif //ndef BUILD_TWRPTAR_MAIN
401 }
402 }
403 close(progress_pipe[0]);
404#ifndef BUILD_TWRPTAR_MAIN
405 DataManager::SetValue("tw_file_progress", "");
406 DataManager::SetValue("tw_size_progress", "");
407
408 InfoManager backup_info(backup_folder + partition_name + ".info");
409 backup_info.SetValue("backup_size", size_backup);
410 if (use_compression && use_encryption)
411 backup_info.SetValue("backup_type", 3);
412 else if (use_encryption)
413 backup_info.SetValue("backup_type", 2);
414 else if (use_compression)
415 backup_info.SetValue("backup_type", 1);
416 else
417 backup_info.SetValue("backup_type", 0);
418 backup_info.SetValue("file_count", files_backup);
419 backup_info.SaveValues();
420#endif //ndef BUILD_TWRPTAR_MAIN
Dees_Troy83bd4832013-05-04 12:39:56 +0000421 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500422 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500423 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500424 return 0;
425}
426
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500427int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000428 int status = 0;
429 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500430 int progress_pipe[2], ret;
431
432 if (pipe(progress_pipe) < 0) {
433 LOGERR("Error creating progress tracking pipe\n");
434 return -1;
435 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000436
437 pid = fork();
438 if (pid >= 0) // fork was successful
439 {
440 if (pid == 0) // child process
441 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500442 close(progress_pipe[0]);
443 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000444 if (TWFunc::Path_Exists(tarfn)) {
445 LOGINFO("Single archive\n");
446 if (extract() != 0)
447 _exit(-1);
448 else
449 _exit(0);
450 } else {
451 LOGINFO("Multiple archives\n");
452 string temp;
453 char actual_filename[255];
454 twrpTar tars[9];
455 pthread_t tar_thread[9];
456 pthread_attr_t tattr;
457 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
458 void *thread_return;
459
460 basefn = tarfn;
461 temp = basefn + "%i%02i";
462 tarfn += "000";
463 if (!TWFunc::Path_Exists(tarfn)) {
464 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500465 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000466 _exit(-1);
467 }
468 if (TWFunc::Get_File_Type(tarfn) != 2) {
469 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
470 tars[0].basefn = basefn;
471 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500472 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000473 if (extractMulti((void*)&tars[0]) != 0) {
474 LOGERR("Error extracting split archive.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500475 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000476 _exit(-1);
477 }
478 } else {
479 start_thread_id = 0;
480 }
481 // Start threading encrypted restores
482 if (pthread_attr_init(&tattr)) {
483 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500484 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000485 _exit(-1);
486 }
487 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
488 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500489 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000490 _exit(-1);
491 }
492 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
493 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500494 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000495 _exit(-1);
496 }
497 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
498 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500499 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000500 _exit(-1);
501 }*/
502 for (i = start_thread_id; i < 9; i++) {
503 sprintf(actual_filename, temp.c_str(), i, 0);
504 if (TWFunc::Path_Exists(actual_filename)) {
505 thread_count++;
506 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500507 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000508 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500509 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000510 LOGINFO("Creating extract thread ID %i\n", i);
511 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
512 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500513 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 +0000514 if (extractMulti((void*)&tars[i]) != 0) {
515 LOGERR("Error extracting backup in thread %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500516 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000517 _exit(-1);
518 } else {
519 tars[i].thread_id = i + 1;
520 }
521 }
522 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
523 } else {
524 break;
525 }
526 }
527 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
528 if (tars[i].thread_id == i) {
529 if (pthread_join(tar_thread[i], &thread_return)) {
530 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500531 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000532 _exit(-1);
533 } else {
534 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600535 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000536 if (ret != 0) {
537 thread_error = 1;
538 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500539 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000540 _exit(-1);
541 }
542 }
543 } else {
544 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
545 }
546 }
547 if (thread_error) {
548 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500549 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000550 _exit(-1);
551 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500552 LOGINFO("Finished encrypted restore.\n");
553 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000554 _exit(0);
555 }
556 }
557 else // parent process
558 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500559 unsigned long long fs, size_backup;
560 double display_percent, progress_percent;
561 char size_progress[1024];
562 size_backup = 0;
563
564 // Parent closes output side
565 close(progress_pipe[1]);
566
567 // Read progress data from children
568 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
569 size_backup += fs;
570 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
571 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
572 progress_percent = (display_percent / 100);
573#ifndef BUILD_TWRPTAR_MAIN
574 DataManager::SetValue("tw_size_progress", size_progress);
575 DataManager::SetProgress((float)(progress_percent));
576#endif //ndef BUILD_TWRPTAR_MAIN
577 }
578 close(progress_pipe[0]);
579#ifndef BUILD_TWRPTAR_MAIN
580 DataManager::SetValue("tw_file_progress", "");
581#endif //ndef BUILD_TWRPTAR_MAIN
582 *other_backups_size += size_backup;
583
Dees_Troy83bd4832013-05-04 12:39:56 +0000584 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
585 return -1;
586 }
587 }
588 else // fork has failed
589 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500590 close(progress_pipe[0]);
591 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000592 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500593 return -1;
594 }
595 return 0;
596}
597
Dees_Troy83bd4832013-05-04 12:39:56 +0000598int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
599 DIR* d;
600 struct dirent* de;
601 struct stat st;
602 string FileName;
603 struct TarListStruct TarItem;
604 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500605 int ret, file_count;
606 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000607
Dees_Troy83bd4832013-05-04 12:39:56 +0000608 d = opendir(Path.c_str());
609 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000610 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000611 closedir(d);
612 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500613 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000614 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500615 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500616
Matt Mower50248ab2014-03-31 15:58:40 -0500617 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000618 continue;
619 TarItem.fn = FileName;
620 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500621 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000622 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500623 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
624 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500625 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500626 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000627 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
628 stat(FileName.c_str(), &st);
629 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500630 if (de->d_type == DT_REG) {
631 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000632 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500633 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000634 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
635 *thread_id = *thread_id + 1;
636 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500637 }
638 }
639 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000640 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500641 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500642}
643
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500644int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000645 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000646 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500647 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500648 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000649 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500650 return -1;
651 }
652 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000653 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500654 return -1;
655 }
656 return 0;
657}
658
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500659int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000660 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200661
662 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500663 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000664 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000665 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500666 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000667 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600668 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000669 if (ret < 1) {
670 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
671 return -1;
672 }
673 if (ret == 1) {
674 LOGERR("Decrypted file is not in tar format.\n");
675 return -1;
676 }
677 if (ret == 3) {
678 LOGINFO("Extracting encrypted and compressed tar.\n");
679 Archive_Current_Type = 3;
680 } else
681 LOGINFO("Extracting encrypted tar.\n");
682 return extractTar();
683 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000684 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500685 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500686 }
687}
688
Dees Troye0a433a2013-12-02 04:10:37 +0000689int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000690 struct stat st;
691 char buf[PATH_MAX];
692 int list_size = TarList->size(), i = 0, archive_count = 0;
693 string temp;
694 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000695 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500696 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000697
Dees Troye0a433a2013-12-02 04:10:37 +0000698 if (split_archives) {
699 basefn = tarfn;
700 temp = basefn + "%i%02i";
701 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
702 tarfn = actual_filename;
703 include_root_dir = true;
704 } else {
705 include_root_dir = false;
706 }
707 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000708 if (createTar() != 0) {
709 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
710 return -2;
711 }
712 Archive_Current_Size = 0;
713
714 while (i < list_size) {
715 if (TarList->at(i).thread_id == thread_id) {
716 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400717 lstat(buf, &st);
718 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500719 fs = (unsigned long long)(st.st_size);
720 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000721 if (closeTar() != 0) {
722 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
723 return -3;
724 }
725 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000726 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000727 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000728 LOGERR("Too many archives for thread %i\n", thread_id);
729 return -4;
730 }
731 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
732 tarfn = actual_filename;
733 if (createTar() != 0) {
734 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
735 return -2;
736 }
737 Archive_Current_Size = 0;
738 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500739 Archive_Current_Size += fs;
740 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000741 }
Dees Troye0a433a2013-12-02 04:10:37 +0000742 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
743 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000744 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
745 return -1;
746 }
747 }
748 i++;
749 }
750 if (closeTar() != 0) {
751 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
752 return -3;
753 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600754 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000755 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500756}
757
Dees_Troy83bd4832013-05-04 12:39:56 +0000758void* twrpTar::createList(void *cookie) {
759
760 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600761 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000762 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
763 return (void*)-2;
764 }
765 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
766 return (void*)0;
767}
768
769void* twrpTar::extractMulti(void *cookie) {
770
771 twrpTar* threadTar = (twrpTar*) cookie;
772 int archive_count = 0;
773 string temp = threadTar->basefn + "%i%02i";
774 char actual_filename[255];
775 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
776 while (TWFunc::Path_Exists(actual_filename)) {
777 threadTar->tarfn = actual_filename;
778 if (threadTar->extract() != 0) {
779 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
780 return (void*)-2;
781 }
782 archive_count++;
783 if (archive_count > 99)
784 break;
785 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
786 }
787 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
788 return (void*)0;
789}
790
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500791int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
792 char* charTarFile = (char*) fn.c_str();
793
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200794 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 -0500795 return -1;
796 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200797 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 -0500798 return -1;
799 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500800 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500801 if (tar_append_file(t, file, file) == -1)
802 return -1;
803 }
804 if (tar_append_eof(t) == -1)
805 return -1;
806 if (tar_close(t) == -1)
807 return -1;
808 return 0;
809}
810
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500811int twrpTar::createTar() {
812 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000813 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000814 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500815
Dees_Troy83bd4832013-05-04 12:39:56 +0000816 if (use_encryption && use_compression) {
817 // Compressed and encrypted
818 Archive_Current_Type = 3;
819 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000820 int i, pipes[4];
821
822 if (pipe(pipes) < 0) {
823 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500824 return -1;
825 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000826 if (pipe(pipes + 2) < 0) {
827 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500828 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000829 }
Dees Troy9d723272014-04-07 17:13:10 +0000830 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);
831 if (output_fd < 0) {
832 LOGERR("Failed to open '%s'\n", tarfn.c_str());
833 for (i = 0; i < 4; i++)
834 close(pipes[i]); // close all
835 return -1;
836 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000837 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400838
Dees_Troy83bd4832013-05-04 12:39:56 +0000839 if (pigz_pid < 0) {
840 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000841 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000842 for (i = 0; i < 4; i++)
843 close(pipes[i]); // close all
844 return -1;
845 } else if (pigz_pid == 0) {
846 // pigz Child
847 close(pipes[1]);
848 close(pipes[2]);
849 close(0);
850 dup2(pipes[0], 0);
851 close(1);
852 dup2(pipes[3], 1);
853 if (execlp("pigz", "pigz", "-", NULL) < 0) {
854 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000855 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000856 close(pipes[0]);
857 close(pipes[3]);
858 _exit(-1);
859 }
860 } else {
861 // Parent
862 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400863
Dees_Troy83bd4832013-05-04 12:39:56 +0000864 if (oaes_pid < 0) {
865 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000866 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000867 for (i = 0; i < 4; i++)
868 close(pipes[i]); // close all
869 return -1;
870 } else if (oaes_pid == 0) {
871 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000872 close(pipes[0]);
873 close(pipes[1]);
874 close(pipes[3]);
875 close(0);
876 dup2(pipes[2], 0);
877 close(1);
878 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600879 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000880 LOGERR("execlp openaes ERROR!\n");
881 close(pipes[2]);
882 close(output_fd);
883 _exit(-1);
884 }
885 } else {
886 // Parent
887 close(pipes[0]);
888 close(pipes[2]);
889 close(pipes[3]);
890 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200891 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 +0000892 close(fd);
893 LOGERR("tar_fdopen failed\n");
894 return -1;
895 }
896 return 0;
897 }
898 }
899 } else if (use_compression) {
900 // Compressed
901 Archive_Current_Type = 1;
902 LOGINFO("Using compression...\n");
903 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000904 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);
905 if (output_fd < 0) {
906 LOGERR("Failed to open '%s'\n", tarfn.c_str());
907 close(pigzfd[0]);
908 return -1;
909 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000910
911 if (pipe(pigzfd) < 0) {
912 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000913 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000914 return -1;
915 }
916 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400917
Dees_Troy83bd4832013-05-04 12:39:56 +0000918 if (pigz_pid < 0) {
919 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000920 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000921 close(pigzfd[0]);
922 close(pigzfd[1]);
923 return -1;
924 } else if (pigz_pid == 0) {
925 // Child
926 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000927 dup2(pigzfd[0], 0); // remap stdin
928 dup2(output_fd, 1); // remap stdout to output file
929 if (execlp("pigz", "pigz", "-", NULL) < 0) {
930 LOGERR("execlp pigz ERROR!\n");
931 close(output_fd);
932 close(pigzfd[0]);
933 _exit(-1);
934 }
935 } else {
936 // Parent
937 close(pigzfd[0]); // close parent input
938 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200939 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 +0000940 close(fd);
941 LOGERR("tar_fdopen failed\n");
942 return -1;
943 }
944 }
945 } else if (use_encryption) {
946 // Encrypted
947 Archive_Current_Type = 2;
948 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000949 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000950 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);
951 if (output_fd < 0) {
952 LOGERR("Failed to open '%s'\n", tarfn.c_str());
953 return -1;
954 }
955 if (pipe(oaesfd) < 0) {
956 LOGERR("Error creating pipe\n");
957 close(output_fd);
958 return -1;
959 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000960 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400961
Dees_Troy83bd4832013-05-04 12:39:56 +0000962 if (oaes_pid < 0) {
963 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000964 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000965 close(oaesfd[0]);
966 close(oaesfd[1]);
967 return -1;
968 } else if (oaes_pid == 0) {
969 // Child
970 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000971 dup2(oaesfd[0], 0); // remap stdin
972 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600973 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000974 LOGERR("execlp openaes ERROR!\n");
975 close(output_fd);
976 close(oaesfd[0]);
977 _exit(-1);
978 }
979 } else {
980 // Parent
981 close(oaesfd[0]); // close parent input
982 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200983 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 +0000984 close(fd);
985 LOGERR("tar_fdopen failed\n");
986 return -1;
987 }
988 return 0;
989 }
990 } else {
991 // Not compressed or encrypted
992 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200993 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 +0000994 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
995 return -1;
996 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500997 }
998 return 0;
999}
1000
Dees_Troy83bd4832013-05-04 12:39:56 +00001001int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001002 char* charRootDir = (char*) tardir.c_str();
1003 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001004 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001005
Dees_Troy83bd4832013-05-04 12:39:56 +00001006 if (Archive_Current_Type == 3) {
1007 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001008 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001009 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1010 if (input_fd < 0) {
1011 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1012 return -1;
1013 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001014
1015 if (pipe(pipes) < 0) {
1016 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001017 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001018 return -1;
1019 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001020 if (pipe(pipes + 2) < 0) {
1021 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001022 close(pipes[0]);
1023 close(pipes[1]);
1024 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001025 return -1;
1026 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001027 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001028
Dees_Troy83bd4832013-05-04 12:39:56 +00001029 if (oaes_pid < 0) {
1030 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001031 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001032 for (i = 0; i < 4; i++)
1033 close(pipes[i]); // close all
1034 return -1;
1035 } else if (oaes_pid == 0) {
1036 // openaes Child
1037 close(pipes[0]); // Close pipes that are not used by this child
1038 close(pipes[2]);
1039 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001040 close(0);
1041 dup2(input_fd, 0);
1042 close(1);
1043 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001044 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001045 LOGERR("execlp openaes ERROR!\n");
1046 close(input_fd);
1047 close(pipes[1]);
1048 _exit(-1);
1049 }
1050 } else {
1051 // Parent
1052 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001053
Dees_Troy83bd4832013-05-04 12:39:56 +00001054 if (pigz_pid < 0) {
1055 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001056 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001057 for (i = 0; i < 4; i++)
1058 close(pipes[i]); // close all
1059 return -1;
1060 } else if (pigz_pid == 0) {
1061 // pigz Child
1062 close(pipes[1]); // Close pipes not used by this child
1063 close(pipes[2]);
1064 close(0);
1065 dup2(pipes[0], 0);
1066 close(1);
1067 dup2(pipes[3], 1);
1068 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1069 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +00001070 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001071 close(pipes[0]);
1072 close(pipes[3]);
1073 _exit(-1);
1074 }
1075 } else {
1076 // Parent
1077 close(pipes[0]); // Close pipes not used by parent
1078 close(pipes[1]);
1079 close(pipes[3]);
1080 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001081 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 +00001082 close(fd);
1083 LOGERR("tar_fdopen failed\n");
1084 return -1;
1085 }
1086 }
1087 }
1088 } else if (Archive_Current_Type == 2) {
1089 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001090 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001091 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1092 if (input_fd < 0) {
1093 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1094 return -1;
1095 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001096
Dees Troy9d723272014-04-07 17:13:10 +00001097 if (pipe(oaesfd) < 0) {
1098 LOGERR("Error creating pipe\n");
1099 close(input_fd);
1100 return -1;
1101 }
1102
Dees_Troy83bd4832013-05-04 12:39:56 +00001103 oaes_pid = fork();
1104 if (oaes_pid < 0) {
1105 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001106 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001107 close(oaesfd[0]);
1108 close(oaesfd[1]);
1109 return -1;
1110 } else if (oaes_pid == 0) {
1111 // Child
1112 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001113 close(0); // close stdin
1114 dup2(oaesfd[1], 1); // remap stdout
1115 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001116 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001117 LOGERR("execlp openaes ERROR!\n");
1118 close(input_fd);
1119 close(oaesfd[1]);
1120 _exit(-1);
1121 }
1122 } else {
1123 // Parent
1124 close(oaesfd[1]); // close parent output
1125 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001126 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 +00001127 close(fd);
1128 LOGERR("tar_fdopen failed\n");
1129 return -1;
1130 }
1131 }
1132 } else if (Archive_Current_Type == 1) {
1133 LOGINFO("Opening as a gzip...\n");
1134 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001135 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1136 if (input_fd < 0) {
1137 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1138 return -1;
1139 }
1140 if (pipe(pigzfd) < 0) {
1141 LOGERR("Error creating pipe\n");
1142 close(input_fd);
1143 return -1;
1144 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001145
1146 pigz_pid = fork();
1147 if (pigz_pid < 0) {
1148 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001149 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001150 close(pigzfd[0]);
1151 close(pigzfd[1]);
1152 return -1;
1153 } else if (pigz_pid == 0) {
1154 // Child
1155 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001156 dup2(input_fd, 0); // remap input fd to stdin
1157 dup2(pigzfd[1], 1); // remap stdout
1158 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1159 close(pigzfd[1]);
1160 close(input_fd);
1161 LOGERR("execlp openaes ERROR!\n");
1162 _exit(-1);
1163 }
1164 } else {
1165 // Parent
1166 close(pigzfd[1]); // close parent output
1167 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001168 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 +00001169 close(fd);
1170 LOGERR("tar_fdopen failed\n");
1171 return -1;
1172 }
1173 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001174 } 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 +00001175 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1176 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001177 }
1178 return 0;
1179}
1180
1181string twrpTar::Strip_Root_Dir(string Path) {
1182 string temp;
1183 size_t slash;
1184
1185 if (Path.substr(0, 1) == "/")
1186 temp = Path.substr(1, Path.size() - 1);
1187 else
1188 temp = Path;
1189 slash = temp.find("/");
1190 if (slash == string::npos)
1191 return temp;
1192 else {
1193 string stripped;
1194
1195 stripped = temp.substr(slash, temp.size() - slash);
1196 return stripped;
1197 }
1198 return temp;
1199}
1200
1201int twrpTar::addFile(string fn, bool include_root) {
1202 char* charTarFile = (char*) fn.c_str();
1203 if (include_root) {
1204 if (tar_append_file(t, charTarFile, NULL) == -1)
1205 return -1;
1206 } else {
1207 string temp = Strip_Root_Dir(fn);
1208 char* charTarPath = (char*) temp.c_str();
1209 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1210 return -1;
1211 }
1212 return 0;
1213}
1214
Dees_Troy83bd4832013-05-04 12:39:56 +00001215int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001216 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001217 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001218 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001219 tar_close(t);
1220 return -1;
1221 }
1222 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001223 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001224 return -1;
1225 }
Dees_Troy2727b992013-08-14 20:09:30 +00001226 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001227 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001228 int status;
1229 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1230 return -1;
1231 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1232 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001233 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001234 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001235 if (use_compression && !use_encryption) {
1236 string gzname = tarfn + ".gz";
1237 if (TWFunc::Path_Exists(gzname)) {
1238 rename(gzname.c_str(), tarfn.c_str());
1239 }
1240 }
1241 if (TWFunc::Get_File_Size(tarfn) == 0) {
1242 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1243 return -1;
1244 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001245 return 0;
1246}
1247
1248int twrpTar::removeEOT(string tarFile) {
1249 char* charTarFile = (char*) tarFile.c_str();
1250 off_t tarFileEnd;
1251 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001252 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001253 tar_skip_regfile(t);
1254 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001255 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001256 if (tar_close(t) == -1)
1257 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001258 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001259 return -1;
1260 return 0;
1261}
1262
n0d33b511632013-03-06 21:14:15 +02001263int twrpTar::entryExists(string entry) {
1264 char* searchstr = (char*)entry.c_str();
1265 int ret;
1266
Dees_Troy83bd4832013-05-04 12:39:56 +00001267 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001268
Dees_Troy83bd4832013-05-04 12:39:56 +00001269 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001270 ret = 0;
1271 else
1272 ret = tar_find(t, searchstr);
1273
Dees_Troy83bd4832013-05-04 12:39:56 +00001274 if (closeTar() != 0)
1275 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001276
1277 return ret;
1278}
1279
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001280unsigned long long twrpTar::get_size() {
1281 if (TWFunc::Path_Exists(tarfn)) {
1282 LOGINFO("Single archive\n");
1283 int type = 0;
1284 return uncompressedSize(tarfn, &type);
1285 } else {
1286 LOGINFO("Multiple archives\n");
1287 string temp;
1288 char actual_filename[255];
1289 int archive_count = 0, i, type = 0, temp_type = 0;
1290 unsigned long long total_restore_size = 0;
1291
1292 basefn = tarfn;
1293 temp = basefn + "%i%02i";
1294 tarfn += "000";
1295 thread_id = 0;
1296 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1297 if (!TWFunc::Path_Exists(actual_filename)) {
1298 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1299 return 0;
1300 }
1301 for (i = 0; i < 9; i++) {
1302 archive_count = 0;
1303 sprintf(actual_filename, temp.c_str(), i, archive_count);
1304 while (TWFunc::Path_Exists(actual_filename)) {
1305 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1306 if (temp_type > type)
1307 type = temp_type;
1308 archive_count++;
1309 if (archive_count > 99)
1310 break;
1311 sprintf(actual_filename, temp.c_str(), i, archive_count);
1312 }
1313 }
1314#ifndef BUILD_TWRPTAR_MAIN
1315 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1316 backup_info.SetValue("backup_size", total_restore_size);
1317 backup_info.SetValue("backup_type", type);
1318 backup_info.SaveValues();
1319#endif //ndef BUILD_TWRPTAR_MAIN
1320 return total_restore_size;
1321 }
1322 return 0;
1323}
1324
1325unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1326 int type = 0;
1327 unsigned long long total_size = 0;
1328 string Tar, Command, result;
1329 vector<string> split;
1330
1331 Tar = TWFunc::Get_Filename(filename);
1332 type = TWFunc::Get_File_Type(filename);
1333 if (type == 0) {
1334 total_size = TWFunc::Get_File_Size(filename);
1335 *archive_type = 0;
1336 } else if (type == 1) {
1337 // Compressed
1338 Command = "pigz -l '" + filename + "'";
1339 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1340 we get the uncompressed size at once. */
1341 TWFunc::Exec_Cmd(Command, result);
1342 if (!result.empty()) {
1343 /* Expected output:
1344 compressed original reduced name
1345 95855838 179403776 -1.3% data.yaffs2.win
1346 ^
1347 split[5]
1348 */
1349 split = TWFunc::split_string(result, ' ', true);
1350 if (split.size() > 4)
1351 total_size = atoi(split[5].c_str());
1352 }
1353 *archive_type = 1;
1354 } else if (type == 2) {
1355 // File is encrypted and may be compressed
1356 int ret = TWFunc::Try_Decrypting_File(filename, password);
1357 *archive_type = 2;
1358 if (ret < 1) {
1359 LOGERR("Failed to decrypt tar file '%s'\n", filename.c_str());
1360 total_size = TWFunc::Get_File_Size(filename);
1361 } else if (ret == 1) {
1362 LOGERR("Decrypted file is not in tar format.\n");
1363 total_size = TWFunc::Get_File_Size(filename);
1364 } else if (ret == 3) {
1365 *archive_type = 3;
1366 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1367 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1368 we get the uncompressed size at once. */
1369 TWFunc::Exec_Cmd(Command, result);
1370 if (!result.empty()) {
1371 LOGINFO("result was: '%s'\n", result.c_str());
1372 /* Expected output:
1373 compressed original reduced name
1374 95855838 179403776 -1.3% data.yaffs2.win
1375 ^
1376 split[5]
1377 */
1378 split = TWFunc::split_string(result, ' ', true);
1379 if (split.size() > 4)
1380 total_size = atoi(split[5].c_str());
1381 }
1382 } else {
1383 total_size = TWFunc::Get_File_Size(filename);
1384 }
1385 }
1386
1387 return total_size;
1388}
1389
Dees_Troye34c1332013-02-06 19:13:00 +00001390extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1391 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001392}