Merge "unzip: fix Mac build." am: 2ea7c7d39f
am: 5a5ad6106d

Change-Id: I8e94dfef723cd7c2f798b8fc11a529a01d03b7a9
diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp
index af70f1d..7332b41 100644
--- a/libziparchive/unzip.cpp
+++ b/libziparchive/unzip.cpp
@@ -15,11 +15,11 @@
  */
 
 #include <errno.h>
-#include <error.h>
 #include <fcntl.h>
 #include <fnmatch.h>
 #include <getopt.h>
 #include <inttypes.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -64,6 +64,20 @@
 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 @@
     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 @@
   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 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 @@
 
   // 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 @@
         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 @@
     // 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 @@
   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 @@
     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 @@
 
 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 @@
     }
   }
 
-  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);