blob: 5d17521310b0e5e074f39efb43183afff2401bea [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"
38#include "common.h"
39#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) {
57 LOGI("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) {
68 LOGI("Tar creation failed\n");
69 return -1;
70 }
71 else {
72 if (WIFSIGNALED(status) != 0) {
73 LOGI("Child process ended with signal: %d\n", WTERMSIG(status));
74 return -1;
75 }
76 else if (WIFEXITED(status) != 0)
77 LOGI("Tar creation successful\n");
78 else {
79 LOGI("Tar creation failed\n");
80 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) {
91 LOGI("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) {
102 LOGI("Tar creation failed\n");
103 return -1;
104 }
105 else {
106 if (WIFSIGNALED(status) != 0) {
107 LOGI("Child process ended with signal: %d\n", WTERMSIG(status));
108 return -1;
109 }
110 else if (WIFEXITED(status) != 0)
111 LOGI("Tar creation successful\n");
112 else {
113 LOGI("Tar creation failed\n");
114 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) {
125 LOGI("create 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) {
136 LOGI("Tar creation failed\n");
137 return -1;
138 }
139 else {
140 if (WIFSIGNALED(status) != 0) {
141 LOGI("Child process ended with signal: %d\n", WTERMSIG(status));
142 return -1;
143 }
144 else if (WIFEXITED(status) != 0)
145 LOGI("Tar creation successful\n");
146 else {
147 LOGI("Tar creation failed\n");
148 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) {
159 LOGI("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) {
170 LOGI("Tar creation failed\n");
171 return -1;
172 }
173 else {
174 if (WIFSIGNALED(status) != 0) {
175 LOGI("Child process ended with signal: %d\n", WTERMSIG(status));
176 return -1;
177 }
178 else if (WIFEXITED(status) != 0)
179 LOGI("Tar creation successful\n");
180 else {
181 LOGI("Tar creation failed\n");
182 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
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500198 LOGI("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 {
203 LOGE("error opening '%s' -- error: %s\n", Path.c_str(), strerror(errno));
204 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
213 if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
214 {
215 unsigned long long folder_size = TWFunc::Get_Folder_Size(FileName, false);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500216 tardir = FileName;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500217 if (Archive_Current_Size + folder_size > MAX_ARCHIVE_SIZE) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500218 LOGI("Calling Generate_Multiple_Archives\n");
219 if (Generate_Multiple_Archives(FileName) < 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500220 return -1;
221 } else {
222 //FileName += "/";
223 LOGI("Adding folder '%s'\n", FileName.c_str());
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500224 tardir = FileName;
225 if (tarDirs(true) < 0)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500226 return -1;
227 Archive_Current_Size += folder_size;
228 }
229 }
230 else if (de->d_type == DT_REG || de->d_type == DT_LNK)
231 {
232 stat(FileName.c_str(), &st);
233
234 if (Archive_Current_Size != 0 && Archive_Current_Size + st.st_size > MAX_ARCHIVE_SIZE) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500235 LOGI("Closing tar '%s', ", tarfn.c_str());
236 closeTar(false);
Dees_Troye34c1332013-02-06 19:13:00 +0000237 reinit_libtar_buffer();
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500238 if (TWFunc::Get_File_Size(tarfn) == 0) {
239 LOGE("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
240 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500241 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500242 Archive_File_Count++;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500243 if (Archive_File_Count > 999) {
244 LOGE("Archive count is too large!\n");
245 return -1;
246 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500247 string temp = basefn + "%03i";
248 sprintf(actual_filename, temp.c_str(), Archive_File_Count);
249 tarfn = actual_filename;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500250 Archive_Current_Size = 0;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500251 LOGI("Creating tar '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500252 ui_print("Creating archive %i...\n", Archive_File_Count + 1);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500253 if (createTar() != 0)
254 return -1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500255 }
256 LOGI("Adding file: '%s'... ", FileName.c_str());
257 if (addFile(FileName, true) < 0)
258 return -1;
259 Archive_Current_Size += st.st_size;
260 LOGI("added successfully, archive size: %llu\n", Archive_Current_Size);
261 if (st.st_size > 2147483648LL)
262 LOGE("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());
263 }
264 }
265 closedir(d);
266 return 0;
267}
268
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500269int twrpTar::Split_Archive()
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500270{
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500271 string temp = tarfn + "%03i";
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500272 char actual_filename[255];
273
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500274 basefn = tarfn;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500275 Archive_File_Count = 0;
276 Archive_Current_Size = 0;
277 sprintf(actual_filename, temp.c_str(), Archive_File_Count);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500278 tarfn = actual_filename;
Dees_Troye34c1332013-02-06 19:13:00 +0000279 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500280 createTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500281 DataManager::GetValue(TW_HAS_DATA_MEDIA, has_data_media);
282 ui_print("Creating archive 1...\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500283 if (Generate_Multiple_Archives(tardir) < 0) {
Dees_Troye34c1332013-02-06 19:13:00 +0000284 LOGE("Error generating multiple archives\n");
285 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500286 return -1;
287 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500288 closeTar(false);
Dees_Troye34c1332013-02-06 19:13:00 +0000289 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500290 LOGI("Done, created %i archives.\n", (Archive_File_Count++));
291 return (Archive_File_Count);
292}
293
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500294int twrpTar::extractTar() {
Dees_Troye34c1332013-02-06 19:13:00 +0000295 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500296 bool gzip = false;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500297 if (openTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500298 return -1;
299 if (tar_extract_all(t, charRootDir) != 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500300 LOGE("Unable to extract tar archive '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500301 return -1;
302 }
303 if (tar_close(t) != 0) {
304 LOGE("Unable to close tar file\n");
305 return -1;
306 }
307 return 0;
308}
309
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500310int twrpTar::extract() {
Dees_Troye34c1332013-02-06 19:13:00 +0000311 int len = 3;
312 char header[len];
313 string::size_type i = 0;
314 int firstbyte = 0;
315 int secondbyte = 0;
316 int ret;
317 ifstream f;
318 f.open(tarfn.c_str(), ios::in | ios::binary);
319 f.get(header, len);
320 firstbyte = header[i] & 0xff;
321 secondbyte = header[++i] & 0xff;
322 f.close();
323 if (firstbyte == 0x1f && secondbyte == 0x8b) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500324 //if you return the extractTGZ function directly, stack crashes happen
325 LOGI("Extracting gzipped tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500326 ret = extractTGZ();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500327 return ret;
328 }
329 else {
330 LOGI("Extracting uncompressed tar\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500331 return extractTar();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500332 }
333}
334
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500335int twrpTar::tarDirs(bool include_root) {
Dees_Troye34c1332013-02-06 19:13:00 +0000336 DIR* d;
337 string mainfolder = tardir + "/", subfolder;
338 char buf[1024];
339 char* charTarFile = (char*) tarfn.c_str();
340 d = opendir(tardir.c_str());
341 if (d != NULL) {
342 struct dirent* de;
343 while ((de = readdir(d)) != NULL) {
344 LOGI("adding %s\n", de->d_name);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500345#ifdef RECOVERY_SDCARD_ON_DATA
Dees_Troye34c1332013-02-06 19:13:00 +0000346 if ((tardir == "/data" || tardir == "/data/") && strcmp(de->d_name, "media") == 0) continue;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500347#endif
Dees_Troye34c1332013-02-06 19:13:00 +0000348 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500349
Dees_Troye34c1332013-02-06 19:13:00 +0000350 subfolder = mainfolder;
351 subfolder += de->d_name;
352 strcpy(buf, subfolder.c_str());
353 if (de->d_type == DT_DIR) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500354 if (include_root) {
Dees_Troye34c1332013-02-06 19:13:00 +0000355 if (tar_append_tree(t, buf, NULL) != 0) {
356 LOGE("Error appending '%s' to tar archive '%s'\n", buf, charTarFile);
357 return -1;
358 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500359 } else {
360 string temp = Strip_Root_Dir(buf);
361 char* charTarPath = (char*) temp.c_str();
362 if (tar_append_tree(t, buf, charTarPath) != 0) {
Dees_Troye34c1332013-02-06 19:13:00 +0000363 LOGE("Error appending '%s' to tar archive '%s'\n", buf, charTarFile);
364 return -1;
365 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500366 }
Dees_Troye34c1332013-02-06 19:13:00 +0000367 } else if (tardir != "/" && (de->d_type == DT_REG || de->d_type == DT_LNK)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500368 if (addFile(buf, include_root) != 0)
369 return -1;
370 }
Dees_Troye34c1332013-02-06 19:13:00 +0000371 fflush(NULL);
372 }
373 closedir(d);
374 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500375 return 0;
376}
377
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500378int twrpTar::createTGZ() {
Dees_Troye34c1332013-02-06 19:13:00 +0000379 bool gzip = true;
380
381 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500382 if (createTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500383 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500384 if (tarDirs(false) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500385 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500386 if (closeTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500387 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000388 free_libtar_buffer();
389 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500390}
391
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500392int twrpTar::create() {
Dees_Troye34c1332013-02-06 19:13:00 +0000393 bool gzip = false;
394
395 init_libtar_buffer(0);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500396 if (createTar() == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500397 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500398 if (tarDirs(false) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500399 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500400 if (closeTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500401 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000402 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500403 return 0;
404}
405
406int twrpTar::addFilesToExistingTar(vector <string> files, string fn) {
407 char* charTarFile = (char*) fn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000408 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500409
Dees_Troye34c1332013-02-06 19:13:00 +0000410 init_libtar_buffer(0);
411 if (tar_open(&t, charTarFile, &type, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500412 return -1;
413 removeEOT(charTarFile);
Dees_Troye34c1332013-02-06 19:13:00 +0000414 if (tar_open(&t, charTarFile, &type, O_WRONLY | O_APPEND | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500415 return -1;
416 for (unsigned int i = 0; i < files.size(); ++i) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500417 char* file = (char*) files.at(i).c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500418 if (tar_append_file(t, file, file) == -1)
419 return -1;
420 }
Dees_Troye34c1332013-02-06 19:13:00 +0000421 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500422 if (tar_append_eof(t) == -1)
423 return -1;
424 if (tar_close(t) == -1)
425 return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000426 free_libtar_buffer();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500427 return 0;
428}
429
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500430int twrpTar::createTar() {
431 char* charTarFile = (char*) tarfn.c_str();
Dees_Troye34c1332013-02-06 19:13:00 +0000432 char* charRootDir = (char*) tardir.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500433 int use_compression = 0;
Dees_Troye34c1332013-02-06 19:13:00 +0000434 static tartype_t type = { open, close, read, write_tar };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500435
436 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500437 if (use_compression) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500438 string cmd = "pigz - > '" + tarfn + "'";
Dees_Troy40bbcf82013-02-12 15:01:53 +0000439 p = __popen(cmd.c_str(), "w");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500440 fd = fileno(p);
441 if (!p) return -1;
Dees_Troye34c1332013-02-06 19:13:00 +0000442 if(tar_fdopen(&t, fd, charRootDir, &type, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500443 pclose(p);
444 return -1;
445 }
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500446 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500447 else {
Dees_Troye34c1332013-02-06 19:13:00 +0000448 if (tar_open(&t, charTarFile, &type, O_WRONLY | O_CREAT | O_LARGEFILE, 0644, TAR_GNU) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500449 return -1;
450 }
451 return 0;
452}
453
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500454int twrpTar::openTar(bool gzip) {
Dees_Troye34c1332013-02-06 19:13:00 +0000455 char* charRootDir = (char*) tardir.c_str();
456 char* charTarFile = (char*) tarfn.c_str();
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500457
458 if (gzip) {
459 LOGI("Opening as a gzip\n");
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500460 string cmd = "pigz -d -c '" + tarfn + "'";
Dees_Troy40bbcf82013-02-12 15:01:53 +0000461 FILE* pipe = __popen(cmd.c_str(), "r");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500462 int fd = fileno(pipe);
463 if (!pipe) return -1;
464 if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
465 LOGI("tar_fdopen returned error\n");
Dees_Troy40bbcf82013-02-12 15:01:53 +0000466 __pclose(pipe);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500467 return -1;
468 }
469 }
470 else {
471 if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, 0644, TAR_GNU) != 0) {
472 LOGE("Unable to open tar archive '%s'\n", charTarFile);
473 return -1;
474 }
475 }
476 return 0;
477}
478
479string twrpTar::Strip_Root_Dir(string Path) {
480 string temp;
481 size_t slash;
482
483 if (Path.substr(0, 1) == "/")
484 temp = Path.substr(1, Path.size() - 1);
485 else
486 temp = Path;
487 slash = temp.find("/");
488 if (slash == string::npos)
489 return temp;
490 else {
491 string stripped;
492
493 stripped = temp.substr(slash, temp.size() - slash);
494 return stripped;
495 }
496 return temp;
497}
498
499int twrpTar::addFile(string fn, bool include_root) {
500 char* charTarFile = (char*) fn.c_str();
501 if (include_root) {
502 if (tar_append_file(t, charTarFile, NULL) == -1)
503 return -1;
504 } else {
505 string temp = Strip_Root_Dir(fn);
506 char* charTarPath = (char*) temp.c_str();
507 if (tar_append_file(t, charTarFile, charTarPath) == -1)
508 return -1;
509 }
510 return 0;
511}
512
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500513int twrpTar::closeTar(bool gzip) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500514 int use_compression;
515 DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
516
Dees_Troye34c1332013-02-06 19:13:00 +0000517 flush_libtar_buffer(t->fd);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500518 if (tar_append_eof(t) != 0) {
519 LOGE("tar_append_eof(): %s\n", strerror(errno));
520 tar_close(t);
521 return -1;
522 }
523 if (tar_close(t) != 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500524 LOGE("Unable to close tar archive: '%s'\n", tarfn.c_str());
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500525 return -1;
526 }
527 if (use_compression || gzip) {
528 LOGI("Closing popen and fd\n");
529 pclose(p);
530 close(fd);
531 }
532 return 0;
533}
534
535int twrpTar::removeEOT(string tarFile) {
536 char* charTarFile = (char*) tarFile.c_str();
537 off_t tarFileEnd;
538 while (th_read(t) == 0) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500539 if (TH_ISREG(t))
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500540 tar_skip_regfile(t);
541 tarFileEnd = lseek(t->fd, 0, SEEK_CUR);
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500542 }
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500543 if (tar_close(t) == -1)
544 return -1;
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500545 if (truncate(charTarFile, tarFileEnd) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500546 return -1;
547 return 0;
548}
549
550int twrpTar::compress(string fn) {
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500551 string cmd = "pigz " + fn;
Dees_Troy40bbcf82013-02-12 15:01:53 +0000552 p = __popen(cmd.c_str(), "r");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500553 if (!p) return -1;
554 char buffer[128];
555 string result = "";
556 while(!feof(p)) {
557 if(fgets(buffer, 128, p) != NULL)
558 result += buffer;
559 }
Dees_Troy40bbcf82013-02-12 15:01:53 +0000560 __pclose(p);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500561 return 0;
562}
563
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500564int twrpTar::extractTGZ() {
565 string splatrootdir(tardir);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500566 bool gzip = true;
Dees_Troye34c1332013-02-06 19:13:00 +0000567 char* splatCharRootDir = (char*) splatrootdir.c_str();
bigbiff bigbiff3bf2b0e2013-01-21 21:26:43 -0500568 if (openTar(gzip) == -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500569 return -1;
570 int ret = tar_extract_all(t, splatCharRootDir);
571 if (tar_close(t) != 0) {
572 LOGE("Unable to close tar file\n");
573 return -1;
574 }
Dees_Troye34c1332013-02-06 19:13:00 +0000575 return 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500576}
Dees_Troye34c1332013-02-06 19:13:00 +0000577
578extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) {
579 return (ssize_t) write_libtar_buffer(fd, buffer, size);
Dees_Troy40bbcf82013-02-12 15:01:53 +0000580}