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