From bcd810622bd075896edb4d8f289eb615270dd100 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Sun, 3 Nov 2019 08:30:33 -0800 Subject: [PATCH] unzip: fix Mac build. Turns out the Mac doesn't have . Add our own "die" function instead, and use it everywhere so the Mac isn't using an untested codepath. One upside to this is that we'll now call ourselves "unzip" even when run as `ziptool unzip ...`, which was awkward to fix with but trivial if we're rolling our own anyway. Test: still works on Linux Change-Id: I9cb1922595a21cd9f6d55a70d67e30090f8b7f21 --- libziparchive/unzip.cpp | 52 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp index af70f1df3..7332b41c1 100644 --- a/libziparchive/unzip.cpp +++ b/libziparchive/unzip.cpp @@ -15,11 +15,11 @@ */ #include -#include #include #include #include #include +#include #include #include #include @@ -64,6 +64,20 @@ static uint64_t total_uncompressed_length = 0; static uint64_t total_compressed_length = 0; static size_t file_count = 0; +static const char* g_progname; + +static void die(int error, const char* fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "%s: ", g_progname); + vfprintf(stderr, fmt, ap); + if (error != 0) fprintf(stderr, ": %s", strerror(error)); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + static bool ShouldInclude(const std::string& name) { // Explicitly excluded? if (!excludes.empty()) { @@ -155,7 +169,7 @@ static bool PromptOverwrite(const std::string& dst) { char* line = nullptr; size_t n; if (getline(&line, &n, stdin) == -1) { - error(1, 0, "(EOF/read error; assuming [N]one...)"); + die(0, "(EOF/read error; assuming [N]one...)"); overwrite_mode = kNever; return false; } @@ -183,10 +197,10 @@ static void ExtractToPipe(ZipArchiveHandle zah, ZipEntry& entry, const std::stri uint8_t* buffer = new uint8_t[entry.uncompressed_length]; int err = ExtractToMemory(zah, &entry, buffer, entry.uncompressed_length); if (err < 0) { - error(1, 0, "failed to extract %s: %s", name.c_str(), ErrorCodeString(err)); + die(0, "failed to extract %s: %s", name.c_str(), ErrorCodeString(err)); } if (!android::base::WriteFully(1, buffer, entry.uncompressed_length)) { - error(1, errno, "failed to write %s to stdout", name.c_str()); + die(errno, "failed to write %s to stdout", name.c_str()); } delete[] buffer; } @@ -194,7 +208,7 @@ static void ExtractToPipe(ZipArchiveHandle zah, ZipEntry& entry, const std::stri static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) { // Bad filename? if (StartsWith(name, "/") || StartsWith(name, "../") || name.find("/../") != std::string::npos) { - error(1, 0, "bad filename %s", name.c_str()); + die(0, "bad filename %s", name.c_str()); } // Where are we actually extracting to (for human-readable output)? @@ -207,7 +221,7 @@ static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& // Ensure the directory hierarchy exists. if (!MakeDirectoryHierarchy(android::base::Dirname(name))) { - error(1, errno, "couldn't create directory hierarchy for %s", dst.c_str()); + die(errno, "couldn't create directory hierarchy for %s", dst.c_str()); } // An entry in a zip file can just be a directory itself. @@ -218,7 +232,7 @@ static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& struct stat sb; if (stat(name.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return; } - error(1, errno, "couldn't extract directory %s", dst.c_str()); + die(errno, "couldn't extract directory %s", dst.c_str()); } return; } @@ -231,12 +245,12 @@ static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& // Either overwrite_mode is kAlways or the user consented to this specific case. fd = open(name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, entry.unix_mode); } - if (fd == -1) error(1, errno, "couldn't create file %s", dst.c_str()); + if (fd == -1) die(errno, "couldn't create file %s", dst.c_str()); // Actually extract into the file. if (!flag_q) printf(" inflating: %s\n", dst.c_str()); int err = ExtractEntryToFile(zah, &entry, fd); - if (err < 0) error(1, 0, "failed to extract %s: %s", dst.c_str(), ErrorCodeString(err)); + if (err < 0) die(0, "failed to extract %s: %s", dst.c_str(), ErrorCodeString(err)); close(fd); } @@ -345,7 +359,7 @@ static void ProcessAll(ZipArchiveHandle zah) { void* cookie; int err = StartIteration(zah, &cookie); if (err != 0) { - error(1, 0, "couldn't iterate %s: %s", archive_name, ErrorCodeString(err)); + die(0, "couldn't iterate %s: %s", archive_name, ErrorCodeString(err)); } ZipEntry entry; @@ -354,7 +368,7 @@ static void ProcessAll(ZipArchiveHandle zah) { if (ShouldInclude(name)) ProcessOne(zah, entry, name); } - if (err < -1) error(1, 0, "failed iterating %s: %s", archive_name, ErrorCodeString(err)); + if (err < -1) die(0, "failed iterating %s: %s", archive_name, ErrorCodeString(err)); EndIteration(cookie); MaybeShowFooter(); @@ -420,14 +434,14 @@ static void HandleCommonOption(int opt) { int main(int argc, char* argv[]) { // Who am I, and what am I doing? - const char* base = basename(argv[0]); - if (!strcmp(base, "ziptool") && argc > 1) return main(argc - 1, argv + 1); - if (!strcmp(base, "unzip")) { + g_progname = basename(argv[0]); + if (!strcmp(g_progname, "ziptool") && argc > 1) return main(argc - 1, argv + 1); + if (!strcmp(g_progname, "unzip")) { role = kUnzip; - } else if (!strcmp(base, "zipinfo")) { + } else if (!strcmp(g_progname, "zipinfo")) { role = kZipinfo; } else { - error(1, 0, "run as ziptool with unzip or zipinfo as the first argument, or symlink"); + die(0, "run as ziptool with unzip or zipinfo as the first argument, or symlink"); } static const struct option opts[] = { @@ -484,19 +498,19 @@ int main(int argc, char* argv[]) { } } - if (!archive_name) error(1, 0, "missing archive filename"); + if (!archive_name) die(0, "missing archive filename"); // We can't support "-" to unzip from stdin because libziparchive relies on mmap. ZipArchiveHandle zah; int32_t err; if ((err = OpenArchive(archive_name, &zah)) != 0) { - error(1, 0, "couldn't open %s: %s", archive_name, ErrorCodeString(err)); + die(0, "couldn't open %s: %s", archive_name, ErrorCodeString(err)); } // Implement -d by changing into that directory. // We'll create implicit directories based on paths in the zip file, but we // require that the -d directory already exists. - if (flag_d && chdir(flag_d) == -1) error(1, errno, "couldn't chdir to %s", flag_d); + if (flag_d && chdir(flag_d) == -1) die(errno, "couldn't chdir to %s", flag_d); ProcessAll(zah);