blob: 7f057df983ffdef4cbc29ca3574aa444367003d5 [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"
Ethan Yonker960f0302014-12-21 21:54:00 -060047extern "C" {
48 #include "set_metadata.h"
49}
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050050#endif //ndef BUILD_TWRPTAR_MAIN
bigbiff bigbiff9c754052013-01-09 09:09:08 -050051
52using namespace std;
53
Dees_Troy83bd4832013-05-04 12:39:56 +000054twrpTar::twrpTar(void) {
55 use_encryption = 0;
56 userdata_encryption = 0;
57 use_compression = 0;
58 split_archives = 0;
59 has_data_media = 0;
60 pigz_pid = 0;
61 oaes_pid = 0;
Dees Troye0a433a2013-12-02 04:10:37 +000062 Total_Backup_Size = 0;
63 include_root_dir = true;
Dees_Troy83bd4832013-05-04 12:39:56 +000064}
65
66twrpTar::~twrpTar(void) {
67 // Do nothing
68}
69
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050070void twrpTar::setfn(string fn) {
71 tarfn = fn;
72}
73
74void twrpTar::setdir(string dir) {
75 tardir = dir;
76}
77
Dees Troye0a433a2013-12-02 04:10:37 +000078void twrpTar::setsize(unsigned long long backup_size) {
79 Total_Backup_Size = backup_size;
80}
81
Ethan Yonker87af5632014-02-10 11:56:35 -060082void twrpTar::setpassword(string pass) {
83 password = pass;
84}
85
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050086int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +000087 int status = 0;
88 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050089 int progress_pipe[2], ret;
90
91 file_count = 0;
92
93 if (pipe(progress_pipe) < 0) {
94 LOGERR("Error creating progress tracking pipe\n");
95 return -1;
96 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050097 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000098 LOGINFO("create tar failed to fork.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -050099 close(progress_pipe[0]);
100 close(progress_pipe[1]);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500101 return -1;
102 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500103 if (pid == 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000104 // Child process
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500105
106 // Child closes input side of progress pipe
107 close(progress_pipe[0]);
108 progress_pipe_fd = progress_pipe[1];
109
Dees_Troy83bd4832013-05-04 12:39:56 +0000110 if (use_encryption || userdata_encryption) {
111 LOGINFO("Using encryption\n");
112 DIR* d;
113 struct dirent* de;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500114 unsigned long long regular_size = 0, encrypt_size = 0, target_size = 0, core_count = 1, total_size;
Dees_Troy83bd4832013-05-04 12:39:56 +0000115 unsigned enc_thread_id = 1, regular_thread_id = 0, i, start_thread_id = 1;
116 int item_len, ret, thread_error = 0;
117 std::vector<TarListStruct> RegularList;
118 std::vector<TarListStruct> EncryptList;
119 string FileName;
120 struct TarListStruct TarItem;
121 twrpTar reg, enc[9];
122 struct stat st;
123 pthread_t enc_thread[9];
124 pthread_attr_t tattr;
125 void *thread_return;
126
127 core_count = sysconf(_SC_NPROCESSORS_CONF);
128 if (core_count > 8)
129 core_count = 8;
130 LOGINFO(" Core Count : %llu\n", core_count);
131 Archive_Current_Size = 0;
132
133 d = opendir(tardir.c_str());
134 if (d == NULL) {
135 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500136 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000137 _exit(-1);
138 }
139 // Figure out the size of all data to be encrypted and create a list of unencrypted files
140 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500141 FileName = tardir + "/" + de->d_name;
142
143 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000144 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500145 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000146 item_len = strlen(de->d_name);
147 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 -0500148 ret = Generate_TarList(FileName, &RegularList, &target_size, &regular_thread_id);
149 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000150 LOGERR("Error in Generate_TarList with regular list!\n");
151 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500152 close(progress_pipe_fd);
153 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000154 _exit(-1);
155 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500156 file_count = (unsigned long long)(ret);
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500157 regular_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000158 } else {
bigbiff bigbiff34684ff2013-12-01 21:03:45 -0500159 encrypt_size += du.Get_Folder_Size(FileName);
Dees_Troy83bd4832013-05-04 12:39:56 +0000160 }
161 } else if (de->d_type == DT_REG) {
162 stat(FileName.c_str(), &st);
163 encrypt_size += (unsigned long long)(st.st_size);
164 }
165 }
166 closedir(d);
167
168 target_size = encrypt_size / core_count;
169 target_size++;
170 LOGINFO(" Unencrypted size: %llu\n", regular_size);
171 LOGINFO(" Encrypted size : %llu\n", encrypt_size);
172 LOGINFO(" Target size : %llu\n", target_size);
173 if (!userdata_encryption) {
174 enc_thread_id = 0;
175 start_thread_id = 0;
176 core_count--;
177 }
178 Archive_Current_Size = 0;
179
180 d = opendir(tardir.c_str());
181 if (d == NULL) {
182 LOGERR("error opening '%s'\n", tardir.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500183 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000184 _exit(-1);
185 }
186 // Divide up the encrypted file list for threading
187 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500188 FileName = tardir + "/" + de->d_name;
189
190 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000191 continue;
Matt Mower50248ab2014-03-31 15:58:40 -0500192 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000193 item_len = strlen(de->d_name);
194 if (userdata_encryption && ((item_len >= 3 && strncmp(de->d_name, "app", 3) == 0) || (item_len >= 6 && strncmp(de->d_name, "dalvik", 6) == 0))) {
195 // Do nothing, we added these to RegularList earlier
196 } else {
Matt Mower50248ab2014-03-31 15:58:40 -0500197 FileName = tardir + "/" + de->d_name;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500198 ret = Generate_TarList(FileName, &EncryptList, &target_size, &enc_thread_id);
199 if (ret < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000200 LOGERR("Error in Generate_TarList with encrypted list!\n");
201 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500202 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000203 _exit(-1);
204 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500205 file_count += (unsigned long long)(ret);
Dees_Troy83bd4832013-05-04 12:39:56 +0000206 }
207 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
208 stat(FileName.c_str(), &st);
209 if (de->d_type == DT_REG)
210 Archive_Current_Size += (unsigned long long)(st.st_size);
211 TarItem.fn = FileName;
212 TarItem.thread_id = enc_thread_id;
213 EncryptList.push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500214 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000215 }
216 }
217 closedir(d);
218 if (enc_thread_id != core_count) {
219 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 -0500220 if (enc_thread_id > core_count) {
221 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000222 _exit(-1);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500223 } else {
Dees_Troy83bd4832013-05-04 12:39:56 +0000224 LOGERR("Continuining anyway.");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500225 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000226 }
227
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500228 // Send file count to parent
229 write(progress_pipe_fd, &file_count, sizeof(file_count));
230 // Send backup size to parent
231 total_size = regular_size + encrypt_size;
232 write(progress_pipe_fd, &total_size, sizeof(total_size));
233
Dees_Troy83bd4832013-05-04 12:39:56 +0000234 if (userdata_encryption) {
235 // Create a backup of unencrypted data
236 reg.setfn(tarfn);
237 reg.ItemList = &RegularList;
238 reg.thread_id = 0;
239 reg.use_encryption = 0;
240 reg.use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000241 reg.split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500242 reg.progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000243 LOGINFO("Creating unencrypted backup...\n");
244 if (createList((void*)&reg) != 0) {
245 LOGERR("Error creating unencrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500246 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000247 _exit(-1);
248 }
249 }
250
251 if (pthread_attr_init(&tattr)) {
252 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500253 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000254 _exit(-1);
255 }
256 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
257 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500258 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000259 _exit(-1);
260 }
261 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
262 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500263 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000264 _exit(-1);
265 }
266 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
267 LOGERR("Error setting pthread_attr_setstacksize\n");
268 _exit(-1);
269 }*/
270
271 // Create threads for the divided up encryption lists
272 for (i = start_thread_id; i <= core_count; i++) {
273 enc[i].setdir(tardir);
274 enc[i].setfn(tarfn);
275 enc[i].ItemList = &EncryptList;
276 enc[i].thread_id = i;
277 enc[i].use_encryption = use_encryption;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500278 enc[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000279 enc[i].use_compression = use_compression;
Dees Troye0a433a2013-12-02 04:10:37 +0000280 enc[i].split_archives = 1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500281 enc[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000282 LOGINFO("Start encryption thread %i\n", i);
283 ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
284 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500285 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 +0000286 if (createList((void*)&enc[i]) != 0) {
287 LOGERR("Error creating encrypted backup %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500288 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000289 _exit(-1);
290 } else {
291 enc[i].thread_id = i + 1;
292 }
293 }
294 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
295 }
296 if (pthread_attr_destroy(&tattr)) {
297 LOGERR("Failed to pthread_attr_destroy\n");
298 }
299 for (i = start_thread_id; i <= core_count; i++) {
300 if (enc[i].thread_id == i) {
301 if (pthread_join(enc_thread[i], &thread_return)) {
302 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500303 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000304 _exit(-1);
305 } else {
306 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600307 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000308 if (ret != 0) {
309 thread_error = 1;
310 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500311 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000312 _exit(-1);
313 }
314 }
315 } else {
316 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
317 }
318 }
319 if (thread_error) {
320 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500321 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000322 _exit(-1);
323 }
324 LOGINFO("Finished encrypted backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500325 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000326 _exit(0);
327 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500328 // Not encrypted
Dees Troye0a433a2013-12-02 04:10:37 +0000329 std::vector<TarListStruct> FileList;
330 unsigned thread_id = 0;
331 unsigned long long target_size = 0;
332 twrpTar reg;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500333 int ret;
Dees Troye0a433a2013-12-02 04:10:37 +0000334
335 // Generate list of files to back up
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500336 ret = Generate_TarList(tardir, &FileList, &target_size, &thread_id);
337 if (ret < 0) {
Dees Troye0a433a2013-12-02 04:10:37 +0000338 LOGERR("Error in Generate_TarList!\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500339 close(progress_pipe[1]);
Dees_Troy83bd4832013-05-04 12:39:56 +0000340 _exit(-1);
Dees Troye0a433a2013-12-02 04:10:37 +0000341 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500342 file_count = (unsigned long long)(ret);
Dees Troye0a433a2013-12-02 04:10:37 +0000343 // Create a backup
344 reg.setfn(tarfn);
345 reg.ItemList = &FileList;
346 reg.thread_id = 0;
347 reg.use_encryption = 0;
348 reg.use_compression = use_compression;
349 reg.setsize(Total_Backup_Size);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500350 reg.progress_pipe_fd = progress_pipe_fd;
Dees Troye0a433a2013-12-02 04:10:37 +0000351 if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
352 gui_print("Breaking backup file into multiple archives...\n");
353 reg.split_archives = 1;
354 } else {
355 reg.split_archives = 0;
356 }
357 LOGINFO("Creating backup...\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500358 write(progress_pipe_fd, &file_count, sizeof(file_count));
359 write(progress_pipe_fd, &Total_Backup_Size, sizeof(Total_Backup_Size));
Dees Troye0a433a2013-12-02 04:10:37 +0000360 if (createList((void*)&reg) != 0) {
361 LOGERR("Error creating backup.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500362 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000363 _exit(-1);
364 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500365 close(progress_pipe[1]);
Dees Troye0a433a2013-12-02 04:10:37 +0000366 _exit(0);
Dees_Troy83bd4832013-05-04 12:39:56 +0000367 }
368 } else {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500369 // Parent side
370 unsigned long long fs, size_backup, files_backup, total_backup_size;
371 int first_data = 0;
372 double display_percent, progress_percent;
373 char file_progress[1024];
374 char size_progress[1024];
375 files_backup = 0;
376 size_backup = 0;
377
378 // Parent closes output side
379 close(progress_pipe[1]);
380
381 // Read progress data from children
382 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
383 if (first_data == 0) {
384 // First incoming data is the file count
385 file_count = fs;
386 if (file_count == 0) file_count = 1; // prevent division by 0 below
387 first_data = 1;
388 } else if (first_data == 1) {
389 // Second incoming data is total size
390 total_backup_size = fs;
391 first_data = 2;
392 } else {
393 files_backup++;
394 size_backup += fs;
395 display_percent = (double)(files_backup) / (double)(file_count) * 100;
396 sprintf(file_progress, "%llu of %llu files, %i%%", files_backup, file_count, (int)(display_percent));
397#ifndef BUILD_TWRPTAR_MAIN
398 DataManager::SetValue("tw_file_progress", file_progress);
399 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
400 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
401 DataManager::SetValue("tw_size_progress", size_progress);
402 progress_percent = (display_percent / 100);
403 DataManager::SetProgress((float)(progress_percent));
404#endif //ndef BUILD_TWRPTAR_MAIN
405 }
406 }
407 close(progress_pipe[0]);
408#ifndef BUILD_TWRPTAR_MAIN
409 DataManager::SetValue("tw_file_progress", "");
410 DataManager::SetValue("tw_size_progress", "");
411
412 InfoManager backup_info(backup_folder + partition_name + ".info");
413 backup_info.SetValue("backup_size", size_backup);
414 if (use_compression && use_encryption)
415 backup_info.SetValue("backup_type", 3);
416 else if (use_encryption)
417 backup_info.SetValue("backup_type", 2);
418 else if (use_compression)
419 backup_info.SetValue("backup_type", 1);
420 else
421 backup_info.SetValue("backup_type", 0);
422 backup_info.SetValue("file_count", files_backup);
423 backup_info.SaveValues();
424#endif //ndef BUILD_TWRPTAR_MAIN
Dees_Troy83bd4832013-05-04 12:39:56 +0000425 if (TWFunc::Wait_For_Child(pid, &status, "createTarFork()") != 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500426 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500427 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500428 return 0;
429}
430
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500431int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000432 int status = 0;
433 pid_t pid, rc_pid;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500434 int progress_pipe[2], ret;
435
436 if (pipe(progress_pipe) < 0) {
437 LOGERR("Error creating progress tracking pipe\n");
438 return -1;
439 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000440
441 pid = fork();
442 if (pid >= 0) // fork was successful
443 {
444 if (pid == 0) // child process
445 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500446 close(progress_pipe[0]);
447 progress_pipe_fd = progress_pipe[1];
Dees_Troy83bd4832013-05-04 12:39:56 +0000448 if (TWFunc::Path_Exists(tarfn)) {
449 LOGINFO("Single archive\n");
450 if (extract() != 0)
451 _exit(-1);
452 else
453 _exit(0);
454 } else {
455 LOGINFO("Multiple archives\n");
456 string temp;
457 char actual_filename[255];
458 twrpTar tars[9];
459 pthread_t tar_thread[9];
460 pthread_attr_t tattr;
461 int thread_count = 0, i, start_thread_id = 1, ret, thread_error = 0;
462 void *thread_return;
463
464 basefn = tarfn;
465 temp = basefn + "%i%02i";
466 tarfn += "000";
467 if (!TWFunc::Path_Exists(tarfn)) {
468 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500469 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000470 _exit(-1);
471 }
472 if (TWFunc::Get_File_Type(tarfn) != 2) {
473 LOGINFO("First tar file '%s' not encrypted\n", tarfn.c_str());
474 tars[0].basefn = basefn;
475 tars[0].thread_id = 0;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500476 tars[0].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000477 if (extractMulti((void*)&tars[0]) != 0) {
478 LOGERR("Error extracting split archive.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500479 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000480 _exit(-1);
481 }
482 } else {
483 start_thread_id = 0;
484 }
485 // Start threading encrypted restores
486 if (pthread_attr_init(&tattr)) {
487 LOGERR("Unable to pthread_attr_init\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500488 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000489 _exit(-1);
490 }
491 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
492 LOGERR("Error setting pthread_attr_setdetachstate\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500493 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000494 _exit(-1);
495 }
496 if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
497 LOGERR("Error setting pthread_attr_setscope\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500498 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000499 _exit(-1);
500 }
501 /*if (pthread_attr_setstacksize(&tattr, 524288)) {
502 LOGERR("Error setting pthread_attr_setstacksize\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500503 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000504 _exit(-1);
505 }*/
506 for (i = start_thread_id; i < 9; i++) {
507 sprintf(actual_filename, temp.c_str(), i, 0);
508 if (TWFunc::Path_Exists(actual_filename)) {
509 thread_count++;
510 tars[i].basefn = basefn;
Ethan Yonker924a80b2014-04-02 10:54:12 -0500511 tars[i].setpassword(password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000512 tars[i].thread_id = i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500513 tars[i].progress_pipe_fd = progress_pipe_fd;
Dees_Troy83bd4832013-05-04 12:39:56 +0000514 LOGINFO("Creating extract thread ID %i\n", i);
515 ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]);
516 if (ret) {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500517 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 +0000518 if (extractMulti((void*)&tars[i]) != 0) {
519 LOGERR("Error extracting backup in thread %i.\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500520 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000521 _exit(-1);
522 } else {
523 tars[i].thread_id = i + 1;
524 }
525 }
526 usleep(100000); // Need a short delay before starting the next thread or the threads will never finish for some reason.
527 } else {
528 break;
529 }
530 }
531 for (i = start_thread_id; i < thread_count + start_thread_id; i++) {
532 if (tars[i].thread_id == i) {
533 if (pthread_join(tar_thread[i], &thread_return)) {
534 LOGERR("Error joining thread %i\n", i);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500535 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000536 _exit(-1);
537 } else {
538 LOGINFO("Joined thread %i.\n", i);
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600539 ret = *((int *)thread_return);
Dees_Troy83bd4832013-05-04 12:39:56 +0000540 if (ret != 0) {
541 thread_error = 1;
542 LOGERR("Thread %i returned an error %i.\n", i, ret);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500543 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000544 _exit(-1);
545 }
546 }
547 } else {
548 LOGINFO("Skipping joining thread %i because of pthread failure.\n", i);
549 }
550 }
551 if (thread_error) {
552 LOGERR("Error returned by one or more threads.\n");
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500553 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000554 _exit(-1);
555 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500556 LOGINFO("Finished encrypted restore.\n");
557 close(progress_pipe_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000558 _exit(0);
559 }
560 }
561 else // parent process
562 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500563 unsigned long long fs, size_backup;
564 double display_percent, progress_percent;
565 char size_progress[1024];
566 size_backup = 0;
567
568 // Parent closes output side
569 close(progress_pipe[1]);
570
571 // Read progress data from children
572 while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) {
573 size_backup += fs;
574 display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100;
575 sprintf(size_progress, "%lluMB of %lluMB, %i%%", (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent));
576 progress_percent = (display_percent / 100);
577#ifndef BUILD_TWRPTAR_MAIN
578 DataManager::SetValue("tw_size_progress", size_progress);
579 DataManager::SetProgress((float)(progress_percent));
580#endif //ndef BUILD_TWRPTAR_MAIN
581 }
582 close(progress_pipe[0]);
583#ifndef BUILD_TWRPTAR_MAIN
584 DataManager::SetValue("tw_file_progress", "");
585#endif //ndef BUILD_TWRPTAR_MAIN
586 *other_backups_size += size_backup;
587
Dees_Troy83bd4832013-05-04 12:39:56 +0000588 if (TWFunc::Wait_For_Child(pid, &status, "extractTarFork()") != 0)
589 return -1;
590 }
591 }
592 else // fork has failed
593 {
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500594 close(progress_pipe[0]);
595 close(progress_pipe[1]);
Dees_Troy2673cec2013-04-02 20:22:16 +0000596 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500597 return -1;
598 }
599 return 0;
600}
601
Dees_Troy83bd4832013-05-04 12:39:56 +0000602int twrpTar::Generate_TarList(string Path, std::vector<TarListStruct> *TarList, unsigned long long *Target_Size, unsigned *thread_id) {
603 DIR* d;
604 struct dirent* de;
605 struct stat st;
606 string FileName;
607 struct TarListStruct TarItem;
608 string::size_type i;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500609 int ret, file_count;
610 file_count = 0;
Dees_Troy83bd4832013-05-04 12:39:56 +0000611
Dees_Troy83bd4832013-05-04 12:39:56 +0000612 d = opendir(Path.c_str());
613 if (d == NULL) {
Dees Troye0a433a2013-12-02 04:10:37 +0000614 LOGERR("Error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
Dees_Troy83bd4832013-05-04 12:39:56 +0000615 closedir(d);
616 return -1;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500617 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000618 while ((de = readdir(d)) != NULL) {
Matt Mower50248ab2014-03-31 15:58:40 -0500619 FileName = Path + "/" + de->d_name;
Matt Mowerbb81e5d2014-03-20 18:05:41 -0500620
Matt Mower50248ab2014-03-31 15:58:40 -0500621 if (de->d_type == DT_BLK || de->d_type == DT_CHR || du.check_skip_dirs(FileName))
Dees_Troy83bd4832013-05-04 12:39:56 +0000622 continue;
623 TarItem.fn = FileName;
624 TarItem.thread_id = *thread_id;
Matt Mower50248ab2014-03-31 15:58:40 -0500625 if (de->d_type == DT_DIR) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000626 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500627 ret = Generate_TarList(FileName, TarList, Target_Size, thread_id);
628 if (ret < 0)
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500629 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500630 file_count += ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000631 } else if (de->d_type == DT_REG || de->d_type == DT_LNK) {
632 stat(FileName.c_str(), &st);
633 TarList->push_back(TarItem);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500634 if (de->d_type == DT_REG) {
635 file_count++;
Dees_Troy83bd4832013-05-04 12:39:56 +0000636 Archive_Current_Size += st.st_size;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500637 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000638 if (Archive_Current_Size != 0 && *Target_Size != 0 && Archive_Current_Size > *Target_Size) {
639 *thread_id = *thread_id + 1;
640 Archive_Current_Size = 0;
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500641 }
642 }
643 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000644 closedir(d);
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500645 return file_count;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500646}
647
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500648int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000649 char* charRootDir = (char*) tardir.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +0000650 if (openTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500651 return -1;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500652 if (tar_extract_all(t, charRootDir, &progress_pipe_fd) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000653 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500654 return -1;
655 }
656 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000657 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500658 return -1;
659 }
660 return 0;
661}
662
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500663int twrpTar::extract() {
Dees_Troy83bd4832013-05-04 12:39:56 +0000664 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +0200665
666 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500667 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000668 LOGINFO("Extracting gzipped tar\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000669 int ret = extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500670 return ret;
Dees_Troy83bd4832013-05-04 12:39:56 +0000671 } else if (Archive_Current_Type == 2) {
Ethan Yonker87af5632014-02-10 11:56:35 -0600672 int ret = TWFunc::Try_Decrypting_File(tarfn, password);
Dees_Troy83bd4832013-05-04 12:39:56 +0000673 if (ret < 1) {
674 LOGERR("Failed to decrypt tar file '%s'\n", tarfn.c_str());
675 return -1;
676 }
677 if (ret == 1) {
678 LOGERR("Decrypted file is not in tar format.\n");
679 return -1;
680 }
681 if (ret == 3) {
682 LOGINFO("Extracting encrypted and compressed tar.\n");
683 Archive_Current_Type = 3;
684 } else
685 LOGINFO("Extracting encrypted tar.\n");
686 return extractTar();
687 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000688 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500689 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500690 }
691}
692
Dees Troye0a433a2013-12-02 04:10:37 +0000693int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000694 struct stat st;
695 char buf[PATH_MAX];
696 int list_size = TarList->size(), i = 0, archive_count = 0;
697 string temp;
698 char actual_filename[PATH_MAX];
Dees Troye0a433a2013-12-02 04:10:37 +0000699 char *ptr;
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500700 unsigned long long fs;
Dees_Troye34c1332013-02-06 19:13:00 +0000701
Dees Troye0a433a2013-12-02 04:10:37 +0000702 if (split_archives) {
703 basefn = tarfn;
704 temp = basefn + "%i%02i";
705 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
706 tarfn = actual_filename;
707 include_root_dir = true;
708 } else {
709 include_root_dir = false;
710 }
711 LOGINFO("Creating tar file '%s'\n", tarfn.c_str());
Dees_Troy83bd4832013-05-04 12:39:56 +0000712 if (createTar() != 0) {
713 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
714 return -2;
715 }
716 Archive_Current_Size = 0;
717
718 while (i < list_size) {
719 if (TarList->at(i).thread_id == thread_id) {
720 strcpy(buf, TarList->at(i).fn.c_str());
bigbiff bigbiffec8fc282014-03-16 20:32:50 -0400721 lstat(buf, &st);
722 if (S_ISREG(st.st_mode)) { // item is a regular file
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500723 fs = (unsigned long long)(st.st_size);
724 if (split_archives && Archive_Current_Size + fs > MAX_ARCHIVE_SIZE) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000725 if (closeTar() != 0) {
726 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
727 return -3;
728 }
729 archive_count++;
Dees Troye0a433a2013-12-02 04:10:37 +0000730 gui_print("Splitting thread ID %i into archive %i\n", thread_id, archive_count + 1);
Dees_Troy83bd4832013-05-04 12:39:56 +0000731 if (archive_count > 99) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000732 LOGERR("Too many archives for thread %i\n", thread_id);
733 return -4;
734 }
735 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
736 tarfn = actual_filename;
737 if (createTar() != 0) {
738 LOGERR("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id);
739 return -2;
740 }
741 Archive_Current_Size = 0;
742 }
Ethan Yonker1b7a31b2014-07-03 15:09:22 -0500743 Archive_Current_Size += fs;
744 write(progress_pipe_fd, &fs, sizeof(fs));
Dees_Troy83bd4832013-05-04 12:39:56 +0000745 }
Dees Troye0a433a2013-12-02 04:10:37 +0000746 LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir);
747 if (addFile(buf, include_root_dir) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000748 LOGERR("Error adding file '%s' to '%s'\n", buf, tarfn.c_str());
749 return -1;
750 }
751 }
752 i++;
753 }
754 if (closeTar() != 0) {
755 LOGERR("Error closing '%s' on thread %i\n", tarfn.c_str(), thread_id);
756 return -3;
757 }
Ethan Yonkerbcc502c2014-11-10 11:22:10 -0600758 LOGINFO("Thread id %i tarList done, %i archives.\n", thread_id, archive_count);
Dees_Troye34c1332013-02-06 19:13:00 +0000759 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500760}
761
Dees_Troy83bd4832013-05-04 12:39:56 +0000762void* twrpTar::createList(void *cookie) {
763
764 twrpTar* threadTar = (twrpTar*) cookie;
Ethan Yonkereae42092014-03-07 15:33:13 -0600765 if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000766 LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id);
767 return (void*)-2;
768 }
769 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
770 return (void*)0;
771}
772
773void* twrpTar::extractMulti(void *cookie) {
774
775 twrpTar* threadTar = (twrpTar*) cookie;
776 int archive_count = 0;
777 string temp = threadTar->basefn + "%i%02i";
778 char actual_filename[255];
779 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
780 while (TWFunc::Path_Exists(actual_filename)) {
781 threadTar->tarfn = actual_filename;
782 if (threadTar->extract() != 0) {
783 LOGINFO("Error extracting '%s' in thread ID %i\n", actual_filename, threadTar->thread_id);
784 return (void*)-2;
785 }
786 archive_count++;
787 if (archive_count > 99)
788 break;
789 sprintf(actual_filename, temp.c_str(), threadTar->thread_id, archive_count);
790 }
791 LOGINFO("Thread ID %i finished successfully.\n", threadTar->thread_id);
792 return (void*)0;
793}
794
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500795int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
796 char* charTarFile = (char*) fn.c_str();
797
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200798 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 -0500799 return -1;
800 removeEOT(charTarFile);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200801 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 -0500802 return -1;
803 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500804 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500805 if (tar_append_file(t, file, file) == -1)
806 return -1;
807 }
808 if (tar_append_eof(t) == -1)
809 return -1;
810 if (tar_close(t) == -1)
811 return -1;
812 return 0;
813}
814
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500815int twrpTar::createTar() {
816 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000817 char* charRootDir = (char*) tardir.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000818 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500819
Dees_Troy83bd4832013-05-04 12:39:56 +0000820 if (use_encryption && use_compression) {
821 // Compressed and encrypted
822 Archive_Current_Type = 3;
823 LOGINFO("Using encryption and compression...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000824 int i, pipes[4];
825
826 if (pipe(pipes) < 0) {
827 LOGERR("Error creating first pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500828 return -1;
829 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000830 if (pipe(pipes + 2) < 0) {
831 LOGERR("Error creating second pipe\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500832 return -1;
Dees_Troy83bd4832013-05-04 12:39:56 +0000833 }
Dees Troy9d723272014-04-07 17:13:10 +0000834 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);
835 if (output_fd < 0) {
836 LOGERR("Failed to open '%s'\n", tarfn.c_str());
837 for (i = 0; i < 4; i++)
838 close(pipes[i]); // close all
839 return -1;
840 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000841 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400842
Dees_Troy83bd4832013-05-04 12:39:56 +0000843 if (pigz_pid < 0) {
844 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000845 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000846 for (i = 0; i < 4; i++)
847 close(pipes[i]); // close all
848 return -1;
849 } else if (pigz_pid == 0) {
850 // pigz Child
851 close(pipes[1]);
852 close(pipes[2]);
853 close(0);
854 dup2(pipes[0], 0);
855 close(1);
856 dup2(pipes[3], 1);
857 if (execlp("pigz", "pigz", "-", NULL) < 0) {
858 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +0000859 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000860 close(pipes[0]);
861 close(pipes[3]);
862 _exit(-1);
863 }
864 } else {
865 // Parent
866 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400867
Dees_Troy83bd4832013-05-04 12:39:56 +0000868 if (oaes_pid < 0) {
869 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000870 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000871 for (i = 0; i < 4; i++)
872 close(pipes[i]); // close all
873 return -1;
874 } else if (oaes_pid == 0) {
875 // openaes Child
Dees_Troy83bd4832013-05-04 12:39:56 +0000876 close(pipes[0]);
877 close(pipes[1]);
878 close(pipes[3]);
879 close(0);
880 dup2(pipes[2], 0);
881 close(1);
882 dup2(output_fd, 1);
Ethan Yonker87af5632014-02-10 11:56:35 -0600883 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000884 LOGERR("execlp openaes ERROR!\n");
885 close(pipes[2]);
886 close(output_fd);
887 _exit(-1);
888 }
889 } else {
890 // Parent
891 close(pipes[0]);
892 close(pipes[2]);
893 close(pipes[3]);
894 fd = pipes[1];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200895 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 +0000896 close(fd);
897 LOGERR("tar_fdopen failed\n");
898 return -1;
899 }
900 return 0;
901 }
902 }
903 } else if (use_compression) {
904 // Compressed
905 Archive_Current_Type = 1;
906 LOGINFO("Using compression...\n");
907 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000908 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);
909 if (output_fd < 0) {
910 LOGERR("Failed to open '%s'\n", tarfn.c_str());
911 close(pigzfd[0]);
912 return -1;
913 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000914
915 if (pipe(pigzfd) < 0) {
916 LOGERR("Error creating pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +0000917 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000918 return -1;
919 }
920 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400921
Dees_Troy83bd4832013-05-04 12:39:56 +0000922 if (pigz_pid < 0) {
923 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000924 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000925 close(pigzfd[0]);
926 close(pigzfd[1]);
927 return -1;
928 } else if (pigz_pid == 0) {
929 // Child
930 close(pigzfd[1]); // close unused output pipe
Dees_Troy83bd4832013-05-04 12:39:56 +0000931 dup2(pigzfd[0], 0); // remap stdin
932 dup2(output_fd, 1); // remap stdout to output file
933 if (execlp("pigz", "pigz", "-", NULL) < 0) {
934 LOGERR("execlp pigz ERROR!\n");
935 close(output_fd);
936 close(pigzfd[0]);
937 _exit(-1);
938 }
939 } else {
940 // Parent
941 close(pigzfd[0]); // close parent input
942 fd = pigzfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200943 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 +0000944 close(fd);
945 LOGERR("tar_fdopen failed\n");
946 return -1;
947 }
948 }
949 } else if (use_encryption) {
950 // Encrypted
951 Archive_Current_Type = 2;
952 LOGINFO("Using encryption...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +0000953 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +0000954 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);
955 if (output_fd < 0) {
956 LOGERR("Failed to open '%s'\n", tarfn.c_str());
957 return -1;
958 }
959 if (pipe(oaesfd) < 0) {
960 LOGERR("Error creating pipe\n");
961 close(output_fd);
962 return -1;
963 }
Dees_Troy83bd4832013-05-04 12:39:56 +0000964 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -0400965
Dees_Troy83bd4832013-05-04 12:39:56 +0000966 if (oaes_pid < 0) {
967 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +0000968 close(output_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +0000969 close(oaesfd[0]);
970 close(oaesfd[1]);
971 return -1;
972 } else if (oaes_pid == 0) {
973 // Child
974 close(oaesfd[1]); // close unused
Dees_Troy83bd4832013-05-04 12:39:56 +0000975 dup2(oaesfd[0], 0); // remap stdin
976 dup2(output_fd, 1); // remap stdout to output file
Ethan Yonker87af5632014-02-10 11:56:35 -0600977 if (execlp("openaes", "openaes", "enc", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +0000978 LOGERR("execlp openaes ERROR!\n");
979 close(output_fd);
980 close(oaesfd[0]);
981 _exit(-1);
982 }
983 } else {
984 // Parent
985 close(oaesfd[0]); // close parent input
986 fd = oaesfd[1]; // copy parent output
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200987 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 +0000988 close(fd);
989 LOGERR("tar_fdopen failed\n");
990 return -1;
991 }
992 return 0;
993 }
994 } else {
995 // Not compressed or encrypted
996 init_libtar_buffer(0);
Vojtech Bocek25fd68d2013-08-27 03:10:10 +0200997 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 +0000998 LOGERR("tar_open error opening '%s'\n", tarfn.c_str());
999 return -1;
1000 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001001 }
1002 return 0;
1003}
1004
Dees_Troy83bd4832013-05-04 12:39:56 +00001005int twrpTar::openTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001006 char* charRootDir = (char*) tardir.c_str();
1007 char* charTarFile = (char*) tarfn.c_str();
Dees_Troy83bd4832013-05-04 12:39:56 +00001008 string Password;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001009
Dees_Troy83bd4832013-05-04 12:39:56 +00001010 if (Archive_Current_Type == 3) {
1011 LOGINFO("Opening encrypted and compressed backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001012 int i, pipes[4];
Dees Troy9d723272014-04-07 17:13:10 +00001013 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1014 if (input_fd < 0) {
1015 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1016 return -1;
1017 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001018
1019 if (pipe(pipes) < 0) {
1020 LOGERR("Error creating first pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001021 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001022 return -1;
1023 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001024 if (pipe(pipes + 2) < 0) {
1025 LOGERR("Error creating second pipe\n");
Dees Troy9d723272014-04-07 17:13:10 +00001026 close(pipes[0]);
1027 close(pipes[1]);
1028 close(input_fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001029 return -1;
1030 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001031 oaes_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001032
Dees_Troy83bd4832013-05-04 12:39:56 +00001033 if (oaes_pid < 0) {
1034 LOGERR("pigz fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001035 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001036 for (i = 0; i < 4; i++)
1037 close(pipes[i]); // close all
1038 return -1;
1039 } else if (oaes_pid == 0) {
1040 // openaes Child
1041 close(pipes[0]); // Close pipes that are not used by this child
1042 close(pipes[2]);
1043 close(pipes[3]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001044 close(0);
1045 dup2(input_fd, 0);
1046 close(1);
1047 dup2(pipes[1], 1);
Ethan Yonker87af5632014-02-10 11:56:35 -06001048 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001049 LOGERR("execlp openaes ERROR!\n");
1050 close(input_fd);
1051 close(pipes[1]);
1052 _exit(-1);
1053 }
1054 } else {
1055 // Parent
1056 pigz_pid = fork();
bigbiff bigbiff86e77bc2013-08-26 21:36:23 -04001057
Dees_Troy83bd4832013-05-04 12:39:56 +00001058 if (pigz_pid < 0) {
1059 LOGERR("openaes fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001060 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001061 for (i = 0; i < 4; i++)
1062 close(pipes[i]); // close all
1063 return -1;
1064 } else if (pigz_pid == 0) {
1065 // pigz Child
1066 close(pipes[1]); // Close pipes not used by this child
1067 close(pipes[2]);
1068 close(0);
1069 dup2(pipes[0], 0);
1070 close(1);
1071 dup2(pipes[3], 1);
1072 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1073 LOGERR("execlp pigz ERROR!\n");
Dees Troy9d723272014-04-07 17:13:10 +00001074 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001075 close(pipes[0]);
1076 close(pipes[3]);
1077 _exit(-1);
1078 }
1079 } else {
1080 // Parent
1081 close(pipes[0]); // Close pipes not used by parent
1082 close(pipes[1]);
1083 close(pipes[3]);
1084 fd = pipes[2];
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001085 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 +00001086 close(fd);
1087 LOGERR("tar_fdopen failed\n");
1088 return -1;
1089 }
1090 }
1091 }
1092 } else if (Archive_Current_Type == 2) {
1093 LOGINFO("Opening encrypted backup...\n");
Dees_Troy83bd4832013-05-04 12:39:56 +00001094 int oaesfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001095 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1096 if (input_fd < 0) {
1097 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1098 return -1;
1099 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001100
Dees Troy9d723272014-04-07 17:13:10 +00001101 if (pipe(oaesfd) < 0) {
1102 LOGERR("Error creating pipe\n");
1103 close(input_fd);
1104 return -1;
1105 }
1106
Dees_Troy83bd4832013-05-04 12:39:56 +00001107 oaes_pid = fork();
1108 if (oaes_pid < 0) {
1109 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001110 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001111 close(oaesfd[0]);
1112 close(oaesfd[1]);
1113 return -1;
1114 } else if (oaes_pid == 0) {
1115 // Child
1116 close(oaesfd[0]); // Close unused pipe
Dees_Troy83bd4832013-05-04 12:39:56 +00001117 close(0); // close stdin
1118 dup2(oaesfd[1], 1); // remap stdout
1119 dup2(input_fd, 0); // remap input fd to stdin
Ethan Yonker87af5632014-02-10 11:56:35 -06001120 if (execlp("openaes", "openaes", "dec", "--key", password.c_str(), NULL) < 0) {
Dees_Troy83bd4832013-05-04 12:39:56 +00001121 LOGERR("execlp openaes ERROR!\n");
1122 close(input_fd);
1123 close(oaesfd[1]);
1124 _exit(-1);
1125 }
1126 } else {
1127 // Parent
1128 close(oaesfd[1]); // close parent output
1129 fd = oaesfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001130 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 +00001131 close(fd);
1132 LOGERR("tar_fdopen failed\n");
1133 return -1;
1134 }
1135 }
1136 } else if (Archive_Current_Type == 1) {
1137 LOGINFO("Opening as a gzip...\n");
1138 int pigzfd[2];
Dees Troy9d723272014-04-07 17:13:10 +00001139 int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE);
1140 if (input_fd < 0) {
1141 LOGERR("Failed to open '%s'\n", tarfn.c_str());
1142 return -1;
1143 }
1144 if (pipe(pigzfd) < 0) {
1145 LOGERR("Error creating pipe\n");
1146 close(input_fd);
1147 return -1;
1148 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001149
1150 pigz_pid = fork();
1151 if (pigz_pid < 0) {
1152 LOGERR("fork() failed\n");
Dees Troy9d723272014-04-07 17:13:10 +00001153 close(input_fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001154 close(pigzfd[0]);
1155 close(pigzfd[1]);
1156 return -1;
1157 } else if (pigz_pid == 0) {
1158 // Child
1159 close(pigzfd[0]);
Dees_Troy83bd4832013-05-04 12:39:56 +00001160 dup2(input_fd, 0); // remap input fd to stdin
1161 dup2(pigzfd[1], 1); // remap stdout
1162 if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) {
1163 close(pigzfd[1]);
1164 close(input_fd);
1165 LOGERR("execlp openaes ERROR!\n");
1166 _exit(-1);
1167 }
1168 } else {
1169 // Parent
1170 close(pigzfd[1]); // close parent output
1171 fd = pigzfd[0]; // copy parent input
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001172 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 +00001173 close(fd);
1174 LOGERR("tar_fdopen failed\n");
1175 return -1;
1176 }
1177 }
Vojtech Bocek25fd68d2013-08-27 03:10:10 +02001178 } 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 +00001179 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
1180 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001181 }
1182 return 0;
1183}
1184
1185string twrpTar::Strip_Root_Dir(string Path) {
1186 string temp;
1187 size_t slash;
1188
1189 if (Path.substr(0, 1) == "/")
1190 temp = Path.substr(1, Path.size() - 1);
1191 else
1192 temp = Path;
1193 slash = temp.find("/");
1194 if (slash == string::npos)
1195 return temp;
1196 else {
1197 string stripped;
1198
1199 stripped = temp.substr(slash, temp.size() - slash);
1200 return stripped;
1201 }
1202 return temp;
1203}
1204
1205int twrpTar::addFile(string fn, bool include_root) {
1206 char* charTarFile = (char*) fn.c_str();
1207 if (include_root) {
1208 if (tar_append_file(t, charTarFile, NULL) == -1)
1209 return -1;
1210 } else {
1211 string temp = Strip_Root_Dir(fn);
1212 char* charTarPath = (char*) temp.c_str();
1213 if (tar_append_file(t, charTarFile, charTarPath) == -1)
1214 return -1;
1215 }
1216 return 0;
1217}
1218
Dees_Troy83bd4832013-05-04 12:39:56 +00001219int twrpTar::closeTar() {
Dees_Troye34c1332013-02-06 19:13:00 +00001220 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001221 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001222 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001223 tar_close(t);
1224 return -1;
1225 }
1226 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +00001227 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001228 return -1;
1229 }
Dees_Troy2727b992013-08-14 20:09:30 +00001230 if (Archive_Current_Type > 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001231 close(fd);
Dees_Troy83bd4832013-05-04 12:39:56 +00001232 int status;
1233 if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0)
1234 return -1;
1235 if (oaes_pid > 0 && TWFunc::Wait_For_Child(oaes_pid, &status, "openaes") != 0)
1236 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001237 }
Dees_Troy83bd4832013-05-04 12:39:56 +00001238 free_libtar_buffer();
Dees Troye0a433a2013-12-02 04:10:37 +00001239 if (use_compression && !use_encryption) {
1240 string gzname = tarfn + ".gz";
1241 if (TWFunc::Path_Exists(gzname)) {
1242 rename(gzname.c_str(), tarfn.c_str());
1243 }
1244 }
1245 if (TWFunc::Get_File_Size(tarfn) == 0) {
1246 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
1247 return -1;
1248 }
Ethan Yonker960f0302014-12-21 21:54:00 -06001249#ifndef BUILD_TWRPTAR_MAIN
Ethan Yonker4b94cfd2014-12-11 10:00:45 -06001250 tw_set_default_metadata(tarfn.c_str());
Ethan Yonker960f0302014-12-21 21:54:00 -06001251#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001252 return 0;
1253}
1254
1255int twrpTar::removeEOT(string tarFile) {
1256 char* charTarFile = (char*) tarFile.c_str();
1257 off_t tarFileEnd;
1258 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001259 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001260 tar_skip_regfile(t);
1261 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001262 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001263 if (tar_close(t) == -1)
1264 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -05001265 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001266 return -1;
1267 return 0;
1268}
1269
n0d33b511632013-03-06 21:14:15 +02001270int twrpTar::entryExists(string entry) {
1271 char* searchstr = (char*)entry.c_str();
1272 int ret;
1273
Dees_Troy83bd4832013-05-04 12:39:56 +00001274 Archive_Current_Type = TWFunc::Get_File_Type(tarfn);
n0d33b511632013-03-06 21:14:15 +02001275
Dees_Troy83bd4832013-05-04 12:39:56 +00001276 if (openTar() == -1)
n0d33b511632013-03-06 21:14:15 +02001277 ret = 0;
1278 else
1279 ret = tar_find(t, searchstr);
1280
Dees_Troy83bd4832013-05-04 12:39:56 +00001281 if (closeTar() != 0)
1282 LOGINFO("Unable to close tar after searching for entry.\n");
n0d33b511632013-03-06 21:14:15 +02001283
1284 return ret;
1285}
1286
Ethan Yonker1b7a31b2014-07-03 15:09:22 -05001287unsigned long long twrpTar::get_size() {
1288 if (TWFunc::Path_Exists(tarfn)) {
1289 LOGINFO("Single archive\n");
1290 int type = 0;
1291 return uncompressedSize(tarfn, &type);
1292 } else {
1293 LOGINFO("Multiple archives\n");
1294 string temp;
1295 char actual_filename[255];
1296 int archive_count = 0, i, type = 0, temp_type = 0;
1297 unsigned long long total_restore_size = 0;
1298
1299 basefn = tarfn;
1300 temp = basefn + "%i%02i";
1301 tarfn += "000";
1302 thread_id = 0;
1303 sprintf(actual_filename, temp.c_str(), thread_id, archive_count);
1304 if (!TWFunc::Path_Exists(actual_filename)) {
1305 LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str());
1306 return 0;
1307 }
1308 for (i = 0; i < 9; i++) {
1309 archive_count = 0;
1310 sprintf(actual_filename, temp.c_str(), i, archive_count);
1311 while (TWFunc::Path_Exists(actual_filename)) {
1312 total_restore_size += uncompressedSize(actual_filename, &temp_type);
1313 if (temp_type > type)
1314 type = temp_type;
1315 archive_count++;
1316 if (archive_count > 99)
1317 break;
1318 sprintf(actual_filename, temp.c_str(), i, archive_count);
1319 }
1320 }
1321#ifndef BUILD_TWRPTAR_MAIN
1322 InfoManager backup_info(backup_folder + "/" + partition_name + ".info");
1323 backup_info.SetValue("backup_size", total_restore_size);
1324 backup_info.SetValue("backup_type", type);
1325 backup_info.SaveValues();
1326#endif //ndef BUILD_TWRPTAR_MAIN
1327 return total_restore_size;
1328 }
1329 return 0;
1330}
1331
1332unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) {
1333 int type = 0;
1334 unsigned long long total_size = 0;
1335 string Tar, Command, result;
1336 vector<string> split;
1337
1338 Tar = TWFunc::Get_Filename(filename);
1339 type = TWFunc::Get_File_Type(filename);
1340 if (type == 0) {
1341 total_size = TWFunc::Get_File_Size(filename);
1342 *archive_type = 0;
1343 } else if (type == 1) {
1344 // Compressed
1345 Command = "pigz -l '" + filename + "'";
1346 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1347 we get the uncompressed size at once. */
1348 TWFunc::Exec_Cmd(Command, result);
1349 if (!result.empty()) {
1350 /* Expected output:
1351 compressed original reduced name
1352 95855838 179403776 -1.3% data.yaffs2.win
1353 ^
1354 split[5]
1355 */
1356 split = TWFunc::split_string(result, ' ', true);
1357 if (split.size() > 4)
1358 total_size = atoi(split[5].c_str());
1359 }
1360 *archive_type = 1;
1361 } else if (type == 2) {
1362 // File is encrypted and may be compressed
1363 int ret = TWFunc::Try_Decrypting_File(filename, password);
1364 *archive_type = 2;
1365 if (ret < 1) {
1366 LOGERR("Failed to decrypt tar file '%s'\n", filename.c_str());
1367 total_size = TWFunc::Get_File_Size(filename);
1368 } else if (ret == 1) {
1369 LOGERR("Decrypted file is not in tar format.\n");
1370 total_size = TWFunc::Get_File_Size(filename);
1371 } else if (ret == 3) {
1372 *archive_type = 3;
1373 Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l";
1374 /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '";
1375 we get the uncompressed size at once. */
1376 TWFunc::Exec_Cmd(Command, result);
1377 if (!result.empty()) {
1378 LOGINFO("result was: '%s'\n", result.c_str());
1379 /* Expected output:
1380 compressed original reduced name
1381 95855838 179403776 -1.3% data.yaffs2.win
1382 ^
1383 split[5]
1384 */
1385 split = TWFunc::split_string(result, ' ', true);
1386 if (split.size() > 4)
1387 total_size = atoi(split[5].c_str());
1388 }
1389 } else {
1390 total_size = TWFunc::Get_File_Size(filename);
1391 }
1392 }
1393
1394 return total_size;
1395}
1396
Dees_Troye34c1332013-02-06 19:13:00 +00001397extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
1398 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +00001399}