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);