Bug 641212 - Part 3: Support XZ-compressed MAR files in the mar command-line tools; r?rstrong draft
authorMatt Howell <mhowell@mozilla.com>
Mon, 28 Nov 2016 14:44:52 -0800
changeset 445552 86f98e76522d564a93b470315504c7febbdf7e96
parent 445551 f18311a53ea078256a9be5bed24bb49897ec928e
child 445553 901bb025170cf4a9b5610338e69096a427948662
push id37551
push usermhowell@mozilla.com
push dateTue, 29 Nov 2016 23:10:16 +0000
reviewersrstrong
bugs641212
milestone53.0a1
Bug 641212 - Part 3: Support XZ-compressed MAR files in the mar command-line tools; r?rstrong MozReview-Commit-ID: 1YVSarCMEHT
modules/libmar/tool/mar.c
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -87,16 +87,38 @@ static void print_usage() {
   printf("  mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
          "-i unsigned_archive_to_refresh.mar\n");
 
   printf("Print executable version:\n");
   printf("  mar --version\n");
   printf("This program does not handle unicode file paths properly\n");
 }
 
+static bool
+mar_decompress(const char *path)
+{
+  static char buffer[512];
+
+  snprintf(buffer, sizeof(buffer), "%s.xz", path);
+  rename(path, buffer);
+
+  snprintf(buffer, sizeof(buffer),
+    "xz --decompress --keep -qq %s.xz", path);
+  return system(buffer) == 0;
+}
+
+static void
+mar_remove_temp(const char *path)
+{
+  static char buffer[512];
+  snprintf(buffer, sizeof(buffer), "%s.xz", path);
+  unlink(path);
+  rename(buffer, path);
+}
+
 static int mar_test_callback(MarFile *mar, 
                              const MarItem *item, 
                              void *unused) {
   printf("%u\t0%o\t%s\n", item->length, item->flags, item->name);
   return 0;
 }
 
 static int mar_test(const char *path) {
@@ -117,16 +139,18 @@ int main(int argc, char **argv) {
   char *NSSConfigDir = NULL;
   const char *certNames[MAX_SIGNATURES];
   char *MARChannelID = MAR_CHANNEL_ID;
   char *productVersion = MOZ_APP_VERSION;
   uint32_t k;
   int rv = -1;
   uint32_t certCount = 0;
   int32_t sigIndex = -1;
+  bool was_compressed = false;
+  int retval = 0;
 
 #if !defined(NO_SIGN_VERIFY)
   uint32_t fileSizes[MAX_SIGNATURES];
   const uint8_t* certBuffers[MAX_SIGNATURES];
 #if ((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX)) || \
     ((defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS))
   char* DERFilePaths[MAX_SIGNATURES];
 #endif
@@ -234,28 +258,32 @@ int main(int argc, char **argv) {
     }
   }
 
   if (argv[1][0] != '-') {
     print_usage();
     return -1;
   }
 
+  was_compressed = mar_decompress(argv[2]);
+
   switch (argv[1][1]) {
   case 'c': {
     struct ProductInformationBlock infoBlock;
     infoBlock.MARChannelID = MARChannelID;
     infoBlock.productVersion = productVersion;
-    return mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
+    retval = mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
+    break;
   }
   case 'i': {
     struct ProductInformationBlock infoBlock;
     infoBlock.MARChannelID = MARChannelID;
     infoBlock.productVersion = productVersion;
-    return refresh_product_info_block(argv[2], &infoBlock);
+    retval = refresh_product_info_block(argv[2], &infoBlock);
+    break;
   }
   case 'T': {
     struct ProductInformationBlock infoBlock;
     uint32_t numSignatures, numAdditionalBlocks;
     int hasSignatureBlock, hasAdditionalBlock;
     if (!get_mar_file_info(argv[2], 
                            &hasSignatureBlock,
                            &numSignatures,
@@ -282,68 +310,79 @@ int main(int argc, char **argv) {
         free((void *)infoBlock.MARChannelID);
         free((void *)infoBlock.productVersion);
       }
      }
     printf("\n");
     /* The fall through from 'T' to 't' is intentional */
   }
   case 't':
-    return mar_test(argv[2]);
+    retval = mar_test(argv[2]);
+    break;
 
   /* Extract a MAR file */
   case 'x':
-    return mar_extract(argv[2]);
+    retval = mar_extract(argv[2]);
+    break;
 
 #ifndef NO_SIGN_VERIFY
   /* Extract a MAR signature */
   case 'X':
     if (sigIndex == -1) {
       fprintf(stderr, "ERROR: Signature index was not passed.\n");
-      return -1;
+      retval = -1;
+      break;
     }
     if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
       fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
               sigIndex);
-      return -1;
+      retval = -1;
+      break;
     }
-    return extract_signature(argv[2], sigIndex, argv[3]);
+    retval = extract_signature(argv[2], sigIndex, argv[3]);
+    break;
 
   /* Import a MAR signature */
   case 'I':
     if (sigIndex == -1) {
       fprintf(stderr, "ERROR: signature index was not passed.\n");
-      return -1;
+      retval = -1;
+      break;
     }
     if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
       fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
               sigIndex);
-      return -1;
+      retval = -1;
+      break;
     }
     if (argc < 5) {
       print_usage();
-      return -1;
+      retval = -1;
+      break;
     }
     return import_signature(argv[2], sigIndex, argv[3], argv[4]);
 
   case 'v':
     if (certCount == 0) {
       print_usage();
-      return -1;
+      retval = -1;
+      break;
     }
 
 #if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
     if (!NSSConfigDir || certCount == 0) {
       print_usage();
-      return -1;
+      retval = -1;
+      break;
     }
 
     if (NSSInitCryptoContext(NSSConfigDir)) {
       fprintf(stderr, "ERROR: Could not initialize crypto library.\n");
-      return -1;
+      retval = -1;
+      break;
     }
 #endif
 
     rv = 0;
     for (k = 0; k < certCount; ++k) {
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
       rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
                                 &certBuffers[k], &fileSizes[k]);
@@ -400,27 +439,33 @@ int main(int argc, char **argv) {
       } else if (!hasSignatureBlock) {
         fprintf(stderr, "ERROR: The MAR file is in the old format so has"
                         " no signature to verify.\n");
       }
     }
 #if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
     (void) NSS_Shutdown();
 #endif
-    return rv ? -1 : 0;
+    retval = rv ? -1 : 0;
 
   case 's':
     if (!NSSConfigDir || certCount == 0 || argc < 4) {
       print_usage();
-      return -1;
+      retval = -1;
+      break;
     }
-    return mar_repackage_and_sign(NSSConfigDir, certNames, certCount,
-                                  argv[2], argv[3]);
-
+    retval = mar_repackage_and_sign(NSSConfigDir, certNames, certCount,
+                                    argv[2], argv[3]);
   case 'r':
-    return strip_signature_block(argv[2], argv[3]);
+    retval = strip_signature_block(argv[2], argv[3]);
 #endif /* endif NO_SIGN_VERIFY disabled */
 
   default:
     print_usage();
-    return -1;
+    retval = -1;
   }
+
+  if (was_compressed) {
+    mar_remove_temp(argv[2]);
+  }
+
+  return retval;
 }