aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/ijar/zip_main.cc
diff options
context:
space:
mode:
authorGravatar Rumou Duan <rduan@google.com>2016-05-12 15:31:07 +0000
committerGravatar Klaus Aehlig <aehlig@google.com>2016-05-12 15:50:07 +0000
commit7942bdc68896116ecdef6180a771095f7fe66a5e (patch)
treeb872726d7b266eb898541f181277c126e4099998 /third_party/ijar/zip_main.cc
parent438ff1677d3f7e5ebe89bf6281c86cd215466eef (diff)
Improvements to zipper extraction support (x option):
1. Add ability to specify relative output directory through -d option. 2. Add ability to specify a list of archive entries to extract from the zip file. Fixes #630. -- MOS_MIGRATED_REVID=122159723
Diffstat (limited to 'third_party/ijar/zip_main.cc')
-rw-r--r--third_party/ijar/zip_main.cc118
1 files changed, 91 insertions, 27 deletions
diff --git a/third_party/ijar/zip_main.cc b/third_party/ijar/zip_main.cc
index 1c55ee9fdc..68c226e9bd 100644
--- a/third_party/ijar/zip_main.cc
+++ b/third_party/ijar/zip_main.cc
@@ -29,6 +29,8 @@
#include <string.h>
#include <unistd.h>
#include <memory>
+#include <set>
+#include <string>
#include "third_party/ijar/zip.h"
@@ -42,27 +44,43 @@ namespace devtools_ijar {
} while (0)
//
-// A ZipExtractorProcessor that extract all files in the ZIP file.
+// A ZipExtractorProcessor that extract files in the ZIP file.
//
class UnzipProcessor : public ZipExtractorProcessor {
public:
- // Create a processor who will extract the files into output_root
- // if "extract" is set to true and will print the list of files and
- // their unix modes if "verbose" is set to true.
- UnzipProcessor(const char *output_root, bool verbose, bool extract)
- : output_root_(output_root), verbose_(verbose), extract_(extract) {}
+ // Create a processor who will extract the given files (or all files if NULL)
+ // into output_root if "extract" is set to true and will print the list of
+ // files and their unix modes if "verbose" is set to true.
+ UnzipProcessor(const char *output_root, char **files, bool verbose,
+ bool extract) : output_root_(output_root),
+ verbose_(verbose),
+ extract_(extract) {
+ if (files != NULL) {
+ for (int i = 0; files[i] != NULL; i++) {
+ file_names.insert(std::string(files[i]));
+ }
+ }
+ }
+
virtual ~UnzipProcessor() {}
virtual void Process(const char* filename, const u4 attr,
const u1* data, const size_t size);
virtual bool Accept(const char* filename, const u4 attr) {
- return true;
+ // All entry files are accepted by default.
+ if (file_names.empty()) {
+ return true;
+ } else {
+ // If users have specified file entries, only accept those files.
+ return file_names.count(std::string(filename)) == 1;
+ }
}
private:
const char *output_root_;
const bool verbose_;
const bool extract_;
+ std::set<std::string> file_names;
};
// Concatene 2 path, path1 and path2, using / as a directory separator and
@@ -125,7 +143,9 @@ void UnzipProcessor::Process(const char* filename, const u4 attr,
char path[PATH_MAX];
int fd;
concat_path(path, PATH_MAX, output_root_, filename);
- mkdirs(path, perm);
+ // Directories created must have executable bit set. Otherwise, we cannot
+ // write or create any file inside.
+ mkdirs(path, perm | S_IXUSR);
if (!isdir) {
fd = open(path, O_CREAT | O_WRONLY, perm);
if (fd < 0) {
@@ -170,14 +190,22 @@ int copy_file_to_buffer(int fd, size_t size, void *buffer) {
}
// Execute the extraction (or just listing if just v is provided)
-int extract(char *zipfile, bool verbose, bool extract) {
- char output_root[PATH_MAX];
- if (getcwd(output_root, PATH_MAX) == NULL) {
+int extract(char *zipfile, char* exdir, char **files, bool verbose,
+ bool extract) {
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, PATH_MAX) == NULL) {
fprintf(stderr, "getcwd() failed: %s.\n", strerror(errno));
return -1;
}
- UnzipProcessor processor(output_root, verbose, extract);
+ char output_root[PATH_MAX];
+ if (exdir != NULL) {
+ concat_path(output_root, PATH_MAX, cwd, exdir);
+ } else {
+ strncpy(output_root, cwd, PATH_MAX);
+ }
+
+ UnzipProcessor processor(output_root, files, verbose, extract);
std::unique_ptr<ZipExtractor> extractor(ZipExtractor::Create(zipfile,
&processor));
if (extractor.get() == NULL) {
@@ -337,9 +365,13 @@ int create(char *zipfile, char **files, bool flatten, bool verbose,
// main method
//
static void usage(char *progname) {
- fprintf(stderr, "Usage: %s [vxc[fC]] x.zip [file1...filen]\n", progname);
+ fprintf(stderr, "Usage: %s [vxc[fC]] x.zip [-d exdir] [file1...filen]\n",
+ progname);
fprintf(stderr, " v verbose - list all file in x.zip\n");
- fprintf(stderr, " x extract - extract file in x.zip in current directory\n");
+ fprintf(stderr,
+ " x extract - extract files in x.zip to current directory, or "
+ " an optional directory relative to the current directory "
+ " specified through -d option\n");
fprintf(stderr, " c create - add files to x.zip\n");
fprintf(stderr, " f flatten - flatten files to use with create operation\n");
fprintf(stderr,
@@ -380,26 +412,58 @@ int main(int argc, char **argv) {
usage(argv[0]);
}
}
- if (create) {
- if (extract) {
- usage(argv[0]);
+
+ // x and c cannot be used in the same command-line.
+ if (create && extract) {
+ usage(argv[0]);
+ }
+
+ // Calculate the argument index of the first entry file.
+ int filelist_start_index;
+ if (argc > 3 && strcmp(argv[3], "-d") == 0) {
+ filelist_start_index = 5;
+ } else {
+ filelist_start_index = 3;
+ }
+
+ char** filelist = NULL;
+
+ // We have one option file. Read and extract the content.
+ if (argc == filelist_start_index + 1 &&
+ argv[filelist_start_index][0] == '@') {
+ char* filelist_name = argv[filelist_start_index];
+ filelist = devtools_ijar::read_filelist(filelist_name + 1);
+ if (filelist == NULL) {
+ fprintf(stderr, "Can't read file list %s: %s.\n", filelist_name,
+ strerror(errno));
+ return -1;
}
- // Create a zip
- char **filelist = argv + 3;
- if (argc == 4 && argv[3][0] == '@') {
- // We never free that list because it needs to be allocated during the
- // whole execution, the system will reclaim memory.
- filelist = devtools_ijar::read_filelist(argv[3] + 1);
- if (filelist == NULL) {
- return -1;
- }
+ // We have more than one files. Assume that they are all file entries.
+ } else if (argc >= filelist_start_index + 1) {
+ filelist = argv + filelist_start_index;
+ } else {
+ // There are no entry files specified. This is forbidden if we are creating
+ // a zip file.
+ if (create) {
+ fprintf(stderr, "Can't create zip without input files specified.");
+ return -1;
}
+ }
+
+ if (create) {
+ // Create a zip
return devtools_ijar::create(argv[2], filelist, flatten, verbose, compress);
} else {
if (flatten) {
usage(argv[0]);
}
+
+ char* exdir = NULL;
+ if (argc > 3 && strcmp(argv[3], "-d") == 0) {
+ exdir = argv[4];
+ }
+
// Extraction / list mode
- return devtools_ijar::extract(argv[2], verbose, extract);
+ return devtools_ijar::extract(argv[2], exdir, filelist, verbose, extract);
}
}