blob: 2dbfd1562056e9194cf919289ee3c3ced857f097 [file] [log] [blame]
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001/*
Dees_Troye34c1332013-02-06 19:13:00 +00002 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05004
Dees_Troye34c1332013-02-06 19:13:00 +00005 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
bigbiff bigbiff9c754052013-01-09 09:09:08 -05009
Dees_Troye34c1332013-02-06 19:13:00 +000010 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050014
Dees_Troye34c1332013-02-06 19:13:00 +000015 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050017*/
18
19extern "C" {
20 #include "libtar/libtar.h"
Dees_Troye34c1332013-02-06 19:13:00 +000021 #include "twrpTar.h"
22 #include "tarWrite.h"
Dees_Troy40bbcf82013-02-12 15:01:53 +000023 #include "libcrecovery/common.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>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050035#include <dirent.h>
36#include <sys/mman.h>
37#include "twrpTar.hpp"
Dees_Troy2673cec2013-04-02 20:22:16 +000038#include "twcommon.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050039#include "data.hpp"
40#include "variables.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050041#include "twrp-functions.hpp"
42
43using namespace std;
44
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050045void twrpTar::setfn(string fn) {
46 tarfn = fn;
47}
48
49void twrpTar::setdir(string dir) {
50 tardir = dir;
51}
52
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050053int twrpTar::createTarGZFork() {
54 int status;
55 pid_t pid;
56 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000057 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050058 return -1;
59 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050060 if (pid == 0) {
61 if (createTGZ() != 0)
62 exit(-1);
63 else
64 exit(0);
65 }
66 else {
67 if ((pid = wait(&status)) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000068 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050069 return -1;
70 }
71 else {
72 if (WIFSIGNALED(status) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +000073 LOGINFO("Child process ended with signal: %d\n", WTERMSIG(status));
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050074 return -1;
75 }
76 else if (WIFEXITED(status) != 0)
Dees_Troy2673cec2013-04-02 20:22:16 +000077 LOGINFO("Tar creation successful\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050078 else {
Dees_Troy2673cec2013-04-02 20:22:16 +000079 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050080 return -1;
81 }
82 }
83 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050084 return 0;
85}
86
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050087int twrpTar::createTarFork() {
88 int status;
89 pid_t pid;
90 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +000091 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -050092 return -1;
93 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -050094 if (pid == 0) {
95 if (create() != 0)
96 exit(-1);
97 else
98 exit(0);
99 }
100 else {
101 if ((pid = wait(&status)) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000102 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500103 return -1;
104 }
105 else {
106 if (WIFSIGNALED(status) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000107 LOGINFO("Child process ended with signal: %d\n", WTERMSIG(status));
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500108 return -1;
109 }
Dees_Troy50d63be2013-03-02 08:49:30 -0600110 else if (WEXITSTATUS(status) == 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000111 LOGINFO("Tar creation successful\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500112 else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000113 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500114 return -1;
115 }
116 }
117 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500118 return 0;
119}
120
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500121int twrpTar::extractTarFork() {
122 int status;
123 pid_t pid;
124 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000125 LOGINFO("extract tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500126 return -1;
127 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500128 if (pid == 0) {
129 if (extract() != 0)
130 exit(-1);
131 else
132 exit(0);
133 }
134 else {
135 if ((pid = wait(&status)) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000136 LOGINFO("Tar extraction failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500137 return -1;
138 }
139 else {
140 if (WIFSIGNALED(status) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000141 LOGINFO("Child process ended with signal: %d\n", WTERMSIG(status));
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500142 return -1;
143 }
Dees_Troy50d63be2013-03-02 08:49:30 -0600144 else if (WEXITSTATUS(status) == 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000145 LOGINFO("Tar extraction successful\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500146 else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000147 LOGINFO("Tar extraction failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500148 return -1;
149 }
150 }
151 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500152 return 0;
153}
154
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500155int twrpTar::splitArchiveFork() {
156 int status;
157 pid_t pid;
158 if ((pid = fork()) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000159 LOGINFO("create tar failed to fork.\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500160 return -1;
161 }
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500162 if (pid == 0) {
163 if (Split_Archive() != 0)
164 exit(-1);
165 else
166 exit(0);
167 }
168 else {
169 if ((pid = wait(&status)) == -1) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000170 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500171 return -1;
172 }
173 else {
174 if (WIFSIGNALED(status) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000175 LOGINFO("Child process ended with signal: %d\n", WTERMSIG(status));
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500176 return -1;
177 }
178 else if (WIFEXITED(status) != 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000179 LOGINFO("Tar creation successful\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500180 else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000181 LOGINFO("Tar creation failed\n");
bigbiff bigbiffe6594ab2013-02-17 20:18:31 -0500182 return -1;
183 }
184 }
185 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500186 return 0;
187}
188
189int twrpTar::Generate_Multiple_Archives(string Path) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500190 DIR* d;
191 struct dirent* de;
192 struct stat st;
193 string FileName;
194 char actual_filename[255];
195
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500196 if (has_data_media == 1 && Path.size() >= 11 && strncmp(Path.c_str(), "/data/media", 11) == 0)
197 return 0; // Skip /data/media
Dees_Troy2673cec2013-04-02 20:22:16 +0000198 LOGINFO("Path: '%s', archive filename: '%s'\n", Path.c_str(), tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500199
200 d = opendir(Path.c_str());
201 if (d == NULL)
202 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000203 LOGERR("error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500204 closedir(d);
205 return -1;
206 }
207 while ((de = readdir(d)) != NULL)
208 {
209 FileName = Path + "/";
210 FileName += de->d_name;
211 if (has_data_media == 1 && FileName.size() >= 11 && strncmp(FileName.c_str(), "/data/media", 11) == 0)
212 continue; // Skip /data/media
bigbiff bigbiff71e5aa42013-02-26 20:10:16 -0500213 if (de->d_type == DT_BLK || de->d_type == DT_CHR)
214 continue;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500215 if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
216 {
217 unsigned long long folder_size = TWFunc::Get_Folder_Size(FileName, false);
218 if (Archive_Current_Size + folder_size > MAX_ARCHIVE_SIZE) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000219 LOGINFO("Calling Generate_Multiple_Archives\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500220 if (Generate_Multiple_Archives(FileName) < 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500221 return -1;
222 } else {
223 //FileName += "/";
Dees_Troy2673cec2013-04-02 20:22:16 +0000224 LOGINFO("Adding folder '%s'\n", FileName.c_str());
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500225 tardir = FileName;
226 if (tarDirs(true) < 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500227 return -1;
228 Archive_Current_Size += folder_size;
229 }
230 }
231 else if (de->d_type == DT_REG || de->d_type == DT_LNK)
232 {
233 stat(FileName.c_str(), &st);
234
235 if (Archive_Current_Size != 0 && Archive_Current_Size + st.st_size > MAX_ARCHIVE_SIZE) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000236 LOGINFO("Closing tar '%s', ", tarfn.c_str());
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500237 closeTar(false);
Dees_Troye34c1332013-02-06 19:13:00 +0000238 reinit_libtar_buffer();
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500239 if (TWFunc::Get_File_Size(tarfn) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000240 LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500241 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500242 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500243 Archive_File_Count++;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500244 if (Archive_File_Count > 999) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000245 LOGERR("Archive count is too large!\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500246 return -1;
247 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500248 string temp = basefn + "%03i";
249 sprintf(actual_filename, temp.c_str(), Archive_File_Count);
250 tarfn = actual_filename;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500251 Archive_Current_Size = 0;
Dees_Troy2673cec2013-04-02 20:22:16 +0000252 LOGINFO("Creating tar '%s'\n", tarfn.c_str());
253 gui_print("Creating archive %i...\n", Archive_File_Count + 1);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500254 if (createTar() != 0)
255 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500256 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000257 LOGINFO("Adding file: '%s'... ", FileName.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500258 if (addFile(FileName, true) < 0)
259 return -1;
260 Archive_Current_Size += st.st_size;
Dees_Troy2673cec2013-04-02 20:22:16 +0000261 LOGINFO("added successfully, archive size: %llu\n", Archive_Current_Size);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500262 if (st.st_size > 2147483648LL)
Dees_Troy2673cec2013-04-02 20:22:16 +0000263 LOGERR("There is a file that is larger than 2GB in the file system\n'%s'\nThis file may not restore properly\n", FileName.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500264 }
265 }
266 closedir(d);
267 return 0;
268}
269
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500270int twrpTar::Split_Archive()
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500271{
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500272 string temp = tarfn + "%03i";
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500273 char actual_filename[255];
274
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500275 basefn = tarfn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500276 Archive_File_Count = 0;
277 Archive_Current_Size = 0;
278 sprintf(actual_filename, temp.c_str(), Archive_File_Count);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500279 tarfn = actual_filename;
Dees_Troye34c1332013-02-06 19:13:00 +0000280 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500281 createTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500282 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
Dees_Troy2673cec2013-04-02 20:22:16 +0000283 gui_print("Creating archive 1...\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500284 if (Generate_Multiple_Archives(tardir) < 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000285 LOGERR("Error generating multiple archives\n");
Dees_Troye34c1332013-02-06 19:13:00 +0000286 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500287 return -1;
288 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500289 closeTar(false);
Dees_Troye34c1332013-02-06 19:13:00 +0000290 free_libtar_buffer();
Dees_Troy2673cec2013-04-02 20:22:16 +0000291 LOGINFO("Done, created %i archives.\n", (Archive_File_Count++));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500292 return (Archive_File_Count);
293}
294
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500295int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000296 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500297 bool gzip = false;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500298 if (openTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500299 return -1;
300 if (tar_extract_all(t, charRootDir) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000301 LOGERR("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500302 return -1;
303 }
304 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000305 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500306 return -1;
307 }
308 return 0;
309}
310
n0d33b511632013-03-06 21:14:15 +0200311int twrpTar::getArchiveType() {
312 int type = 0;
313 string::size_type i = 0;
314 int firstbyte = 0, secondbyte = 0;
315 char header[3];
316
317 ifstream f;
318 f.open(tarfn.c_str(), ios::in | ios::binary);
319 f.get(header, 3);
320 f.close();
321 firstbyte = header[i] & 0xff;
322 secondbyte = header[++i] & 0xff;
323
324 if (firstbyte == 0x1f && secondbyte == 0x8b)
325 type = 1; // Compressed
326 else
327 type = 0; // Uncompressed
328
329 return type;
330}
331
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500332int twrpTar::extract() {
n0d33b511632013-03-06 21:14:15 +0200333 int Archive_Current_Type = getArchiveType();
334
335 if (Archive_Current_Type == 1) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500336 //if you return the extractTGZ function directly, stack crashes happen
Dees_Troy2673cec2013-04-02 20:22:16 +0000337 LOGINFO("Extracting gzipped tar\n");
n0d33b511632013-03-06 21:14:15 +0200338 int ret = extractTGZ();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500339 return ret;
340 }
341 else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000342 LOGINFO("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500343 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500344 }
345}
346
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500347int twrpTar::tarDirs(bool include_root) {
Dees_Troye34c1332013-02-06 19:13:00 +0000348 DIR* d;
349 string mainfolder = tardir + "/", subfolder;
Dees_Troy3263e922013-03-15 11:42:57 -0500350 char buf[PATH_MAX];
Dees_Troye34c1332013-02-06 19:13:00 +0000351 d = opendir(tardir.c_str());
352 if (d != NULL) {
353 struct dirent* de;
354 while ((de = readdir(d)) != NULL) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500355#ifdef RECOVERY_SDCARD_ON_DATA
Dees_Troye34c1332013-02-06 19:13:00 +0000356 if ((tardir == "/data" || tardir == "/data/") && strcmp(de->d_name, "media") == 0) continue;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500357#endif
Dees_Troy3263e922013-03-15 11:42:57 -0500358 if (de->d_type == DT_BLK || de->d_type == DT_CHR || strcmp(de->d_name, "..") == 0)
359 continue;
Dees_Troye34c1332013-02-06 19:13:00 +0000360 subfolder = mainfolder;
Dees_Troy3263e922013-03-15 11:42:57 -0500361 if (strcmp(de->d_name, ".") != 0) {
362 subfolder += de->d_name;
363 } else {
Dees_Troy2673cec2013-04-02 20:22:16 +0000364 LOGINFO("adding '%s'\n", subfolder.c_str());
Dees_Troy3263e922013-03-15 11:42:57 -0500365 if (addFile(subfolder, include_root) != 0)
366 return -1;
367 continue;
368 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000369 LOGINFO("adding '%s'\n", subfolder.c_str());
Dees_Troye34c1332013-02-06 19:13:00 +0000370 strcpy(buf, subfolder.c_str());
371 if (de->d_type == DT_DIR) {
Dees_Troy3263e922013-03-15 11:42:57 -0500372 char* charTarPath;
373 if (include_root) {
374 charTarPath = NULL;
375 } else {
376 string temp = Strip_Root_Dir(buf);
377 charTarPath = (char*) temp.c_str();
378 }
379 if (tar_append_tree(t, buf, charTarPath) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000380 LOGERR("Error appending '%s' to tar archive '%s'\n", buf, tarfn.c_str());
Dees_Troye34c1332013-02-06 19:13:00 +0000381 return -1;
382 }
Dees_Troye34c1332013-02-06 19:13:00 +0000383 } else if (tardir != "/" && (de->d_type == DT_REG || de->d_type == DT_LNK)) {
Dees_Troy3263e922013-03-15 11:42:57 -0500384 if (addFile(buf, include_root) != 0)
385 return -1;
386 }
Dees_Troye34c1332013-02-06 19:13:00 +0000387 fflush(NULL);
388 }
389 closedir(d);
390 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500391 return 0;
392}
393
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500394int twrpTar::createTGZ() {
Dees_Troye34c1332013-02-06 19:13:00 +0000395 bool gzip = true;
396
397 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500398 if (createTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500399 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500400 if (tarDirs(false) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500401 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500402 if (closeTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500403 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000404 free_libtar_buffer();
405 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500406}
407
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500408int twrpTar::create() {
Dees_Troye34c1332013-02-06 19:13:00 +0000409 bool gzip = false;
410
411 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500412 if (createTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500413 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500414 if (tarDirs(false) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500415 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500416 if (closeTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500417 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000418 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500419 return 0;
420}
421
422int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
423 char* charTarFile = (char*) fn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000424 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500425
Dees_Troye34c1332013-02-06 19:13:00 +0000426 init_libtar_buffer(0);
427 if (tar_open(&t, charTarFile, &type, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500428 return -1;
429 removeEOT(charTarFile);
Dees_Troye34c1332013-02-06 19:13:00 +0000430 if (tar_open(&t, charTarFile, &type, O_WRONLY | O_APPEND | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500431 return -1;
432 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500433 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500434 if (tar_append_file(t, file, file) == -1)
435 return -1;
436 }
Dees_Troye34c1332013-02-06 19:13:00 +0000437 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500438 if (tar_append_eof(t) == -1)
439 return -1;
440 if (tar_close(t) == -1)
441 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000442 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500443 return 0;
444}
445
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500446int twrpTar::createTar() {
447 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000448 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500449 int use_compression = 0;
Dees_Troye34c1332013-02-06 19:13:00 +0000450 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500451
452 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500453 if (use_compression) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500454 string cmd = "pigz - > '" + tarfn + "'";
bigbiff bigbiff23aa8192013-02-22 10:43:59 -0500455 p = popen(cmd.c_str(), "w");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500456 fd = fileno(p);
457 if (!p) return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000458 if(tar_fdopen(&t, fd, charRootDir, &type, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500459 pclose(p);
460 return -1;
461 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500462 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500463 else {
Dees_Troye34c1332013-02-06 19:13:00 +0000464 if (tar_open(&t, charTarFile, &type, O_WRONLY | O_CREAT | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500465 return -1;
466 }
467 return 0;
468}
469
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500470int twrpTar::openTar(bool gzip) {
Dees_Troye34c1332013-02-06 19:13:00 +0000471 char* charRootDir = (char*) tardir.c_str();
472 char* charTarFile = (char*) tarfn.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500473
474 if (gzip) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000475 LOGINFO("Opening as a gzip\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500476 string cmd = "pigz -d -c '" + tarfn + "'";
bigbiff bigbiff23aa8192013-02-22 10:43:59 -0500477 FILE* pipe = popen(cmd.c_str(), "r");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500478 int fd = fileno(pipe);
479 if (!pipe) return -1;
480 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000481 LOGINFO("tar_fdopen returned error\n");
Dees_Troy40bbcf82013-02-12 15:01:53 +0000482 __pclose(pipe);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500483 return -1;
484 }
485 }
486 else {
487 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000488 LOGERR("Unable to open tar archive '%s'\n", charTarFile);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500489 return -1;
490 }
491 }
492 return 0;
493}
494
495string twrpTar::Strip_Root_Dir(string Path) {
496 string temp;
497 size_t slash;
498
499 if (Path.substr(0, 1) == "/")
500 temp = Path.substr(1, Path.size() - 1);
501 else
502 temp = Path;
503 slash = temp.find("/");
504 if (slash == string::npos)
505 return temp;
506 else {
507 string stripped;
508
509 stripped = temp.substr(slash, temp.size() - slash);
510 return stripped;
511 }
512 return temp;
513}
514
515int twrpTar::addFile(string fn, bool include_root) {
516 char* charTarFile = (char*) fn.c_str();
517 if (include_root) {
518 if (tar_append_file(t, charTarFile, NULL) == -1)
519 return -1;
520 } else {
521 string temp = Strip_Root_Dir(fn);
522 char* charTarPath = (char*) temp.c_str();
523 if (tar_append_file(t, charTarFile, charTarPath) == -1)
524 return -1;
525 }
526 return 0;
527}
528
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500529int twrpTar::closeTar(bool gzip) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500530 int use_compression;
531 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
532
Dees_Troye34c1332013-02-06 19:13:00 +0000533 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500534 if (tar_append_eof(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000535 LOGERR("tar_append_eof(): %s\n", strerror(errno));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500536 tar_close(t);
537 return -1;
538 }
539 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000540 LOGERR("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500541 return -1;
542 }
543 if (use_compression || gzip) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000544 LOGINFO("Closing popen and fd\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500545 pclose(p);
546 close(fd);
547 }
548 return 0;
549}
550
551int twrpTar::removeEOT(string tarFile) {
552 char* charTarFile = (char*) tarFile.c_str();
553 off_t tarFileEnd;
554 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500555 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500556 tar_skip_regfile(t);
557 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500558 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500559 if (tar_close(t) == -1)
560 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500561 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500562 return -1;
563 return 0;
564}
565
566int twrpTar::compress(string fn) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500567 string cmd = "pigz " + fn;
bigbiff bigbiff23aa8192013-02-22 10:43:59 -0500568 p = popen(cmd.c_str(), "r");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500569 if (!p) return -1;
570 char buffer[128];
571 string result = "";
572 while(!feof(p)) {
573 if(fgets(buffer, 128, p) != NULL)
574 result += buffer;
575 }
Dees_Troy40bbcf82013-02-12 15:01:53 +0000576 __pclose(p);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500577 return 0;
578}
579
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500580int twrpTar::extractTGZ() {
581 string splatrootdir(tardir);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500582 bool gzip = true;
Dees_Troye34c1332013-02-06 19:13:00 +0000583 char* splatCharRootDir = (char*) splatrootdir.c_str();
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500584 if (openTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500585 return -1;
586 int ret = tar_extract_all(t, splatCharRootDir);
587 if (tar_close(t) != 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000588 LOGERR("Unable to close tar file\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500589 return -1;
590 }
Dees_Troye34c1332013-02-06 19:13:00 +0000591 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500592}
Dees_Troye34c1332013-02-06 19:13:00 +0000593
n0d33b511632013-03-06 21:14:15 +0200594int twrpTar::entryExists(string entry) {
595 char* searchstr = (char*)entry.c_str();
596 int ret;
597
598 int Archive_Current_Type = getArchiveType();
599
600 if (openTar(Archive_Current_Type) == -1)
601 ret = 0;
602 else
603 ret = tar_find(t, searchstr);
604
605 if (tar_close(t) != 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000606 LOGINFO("Unable to close tar file after searching for entry '%s'.\n", entry.c_str());
n0d33b511632013-03-06 21:14:15 +0200607
608 return ret;
609}
610
Dees_Troye34c1332013-02-06 19:13:00 +0000611extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
612 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +0000613}