--- a/config/external/moz.build
+++ b/config/external/moz.build
@@ -16,16 +16,18 @@ if not CONFIG['MOZ_SYSTEM_JPEG']:
if CONFIG['MOZ_UPDATER']:
if not CONFIG['MOZ_SYSTEM_BZ2']:
external_dirs += ['modules/libbz2']
# There's no "native" brotli or woff2 yet, but probably in the future...
external_dirs += ['modules/brotli']
external_dirs += ['modules/woff2']
+external_dirs += ['modules/xz-embedded']
+
if CONFIG['MOZ_VORBIS']:
external_dirs += ['media/libvorbis']
if CONFIG['MOZ_TREMOR']:
external_dirs += ['media/libtremor']
if CONFIG['MOZ_WEBM_ENCODER']:
external_dirs += ['media/libmkv']
@@ -56,12 +58,9 @@ external_dirs += [
'media/libopus',
'media/libtheora',
'media/libspeex_resampler',
'media/libstagefright',
'media/libsoundtouch',
'media/psshparser'
]
-if CONFIG['MOZ_LINKER']:
- external_dirs += ['modules/xz-embedded']
-
DIRS += ['../../' + i for i in external_dirs]
--- a/modules/libmar/src/mar.h
+++ b/modules/libmar/src/mar.h
@@ -42,16 +42,22 @@ typedef struct MarItem_ {
uint32_t flags; /* contains file mode bits */
char name[1]; /* file path */
} MarItem;
#define TABLESIZE 256
struct MarFile_ {
FILE *fp;
+ bool decompressed;
+#ifdef XP_WIN
+ wchar_t* name;
+#else
+ char* name;
+#endif
MarItem *item_table[TABLESIZE];
};
typedef struct MarFile_ MarFile;
/**
* Signature of callback function passed to mar_enum_items.
* @param mar The MAR file being visited.
@@ -186,13 +192,34 @@ int mar_verify_signatures(MarFile *mar,
*
* @param infoBlock Out parameter for where to store the result to
* @return 0 on success, -1 on failure
*/
int
mar_read_product_info_block(MarFile *mar,
struct ProductInformationBlock *infoBlock);
+/**
+ * Finds the start and length of the content area of the MAR file.
+ *
+ * @param mar The already opened MAR file
+ * @param[out] contentOffset File offset in bytes of the start of the content,
+ * or -1 if there is no content
+ * @param[out] contentLength Total length of all content files
+*/
+void
+mar_get_content_extent(MarFile* mar, int* contentOffset, int* contentLength);
+
+/**
+* Decompress the content area of a MAR file in place.
+*
+* @param mar The already opened MAR file
+*
+* @return 0 if successful, 1 if the MAR is not compressed, -1 on error
+*/
+int
+mar_decompress(MarFile* mar);
+
#ifdef __cplusplus
}
#endif
#endif /* MAR_H__ */
--- a/modules/libmar/src/mar_create.c
+++ b/modules/libmar/src/mar_create.c
@@ -7,16 +7,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "mar_private.h"
#include "mar_cmdline.h"
#include "mar.h"
+#include "updatedefines.h"
#ifdef XP_WIN
#include <winsock2.h>
#else
#include <netinet/in.h>
#include <unistd.h>
#endif
@@ -294,17 +295,17 @@ refresh_product_info_block(const char *p
int mar_create(const char *dest, int
num_files, char **files,
struct ProductInformationBlock *infoBlock) {
struct MarItemStack stack;
uint32_t offset_to_index = 0, size_of_index,
numSignatures, numAdditionalSections;
uint64_t sizeOfEntireMAR = 0;
struct stat st;
- FILE *fp;
+ FILE *fp, *contentFile = NULL;
int i, rv = -1;
memset(&stack, 0, sizeof(stack));
fp = fopen(dest, "wb");
if (!fp) {
fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
return -1;
@@ -340,60 +341,102 @@ int mar_create(const char *dest, int
goto failure;
}
numAdditionalSections = ntohl(numAdditionalSections);
if (mar_concat_product_info_block(fp, &stack, infoBlock)) {
goto failure;
}
+ // Create a separate file for the content, so we can get it compressed.
+ char contentPath[MAXPATHLEN] = "";
+ snprintf(contentPath, MAXPATHLEN, "%s.content", dest);
+ contentFile = fopen(contentPath, "wb+");
+ if (!contentFile) {
+ goto failure;
+ }
+
for (i = 0; i < num_files; ++i) {
if (stat(files[i], &st)) {
fprintf(stderr, "ERROR: file not found: %s\n", files[i]);
goto failure;
}
if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
goto failure;
/* concatenate input file to archive */
- if (mar_concat_file(fp, files[i]))
+ if (mar_concat_file(contentFile, files[i]))
goto failure;
}
+ // Compress the content.
+ fclose(contentFile);
+ const char command[] = "xz --compress --x86 --lzma2 --format=xz --check=crc64 --force %s";
+ char commandStr[MAXPATHLEN + sizeof(command)] = "";
+ snprintf(commandStr, MAXPATHLEN + sizeof(command), command, contentPath);
+ if (system(commandStr)) {
+ goto failure;
+ }
+
+ // Copy the compressed content into the destination MAR.
+ strncat(contentPath, ".xz", MAXPATHLEN);
+ contentFile = fopen(contentPath, "rb");
+ if (!contentFile) {
+ goto failure;
+ }
+ while (true) {
+ static uint8_t buffer[BLOCKSIZE];
+ size_t bytesRead = fread(buffer, 1, BLOCKSIZE, contentFile);
+ if (bytesRead > 0) {
+ if (fwrite(buffer, 1, bytesRead, fp) != bytesRead) {
+ goto failure;
+ }
+ } else if (feof(contentFile)) {
+ break;
+ } else {
+ goto failure;
+ }
+ }
+
/* write out the index (prefixed with length of index) */
+ offset_to_index = htonl(ftell(fp));
size_of_index = htonl(stack.size_used);
- if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
+ if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1 ||
+ fwrite(stack.head, stack.size_used, 1, fp) != 1) {
goto failure;
- if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
- goto failure;
+ }
/* To protect against invalid MAR files, we assumes that the MAR file
size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
if (ftell(fp) > MAX_SIZE_OF_MAR_FILE) {
goto failure;
}
/* write out offset to index file in network byte order */
- offset_to_index = htonl(stack.last_offset);
- if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
- goto failure;
- if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
+ if (fseek(fp, MAR_ID_SIZE, SEEK_SET) ||
+ fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1) {
goto failure;
- offset_to_index = ntohl(stack.last_offset);
-
- sizeOfEntireMAR = ((uint64_t)stack.last_offset) +
- stack.size_used +
- sizeof(size_of_index);
- sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR);
- if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1)
+ }
+
+ offset_to_index = ntohl(offset_to_index);
+ size_of_index = ntohl(size_of_index);
+ // The +4 is because the size_of_index field does not count itself.
+ sizeOfEntireMAR = HOST_TO_NETWORK64(offset_to_index + size_of_index + 4);
+ if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1) {
goto failure;
- sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);
+ }
rv = 0;
failure:
- if (stack.head)
+ if (stack.head) {
free(stack.head);
+ }
+ if (contentFile) {
+ fclose(contentFile);
+ remove(contentPath);
+ }
fclose(fp);
- if (rv)
+ if (rv) {
remove(dest);
+ }
return rv;
}
new file mode 100644
--- /dev/null
+++ b/modules/libmar/src/mar_decompress.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// for ntohl
+#ifdef XP_WIN
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "updatedefines.h"
+#include "mar_private.h"
+#define XZ_USE_CRC64
+#include "xz.h"
+
+#define FILE_BUFFER_SIZE 262144
+static uint8_t inBuf[FILE_BUFFER_SIZE];
+static uint8_t outBuf[FILE_BUFFER_SIZE];
+
+static int
+mar_decompress_xz_archive(FILE* from, FILE* to)
+{
+ xz_crc32_init();
+ xz_crc64_init();
+
+ // 64 MB is the *maximum* dictionary size; the decoder will allocate up to
+ // that amount, but only if it really needs that much.
+ struct xz_dec * dec = xz_dec_init(XZ_DYNALLOC, 64 * 1024 * 1024);
+ if (!dec) {
+ return -1;
+ }
+
+ struct xz_buf strm = { 0 };
+ strm.in = inBuf;
+ strm.out = outBuf;
+ strm.out_size = FILE_BUFFER_SIZE;
+
+ int rv = 0, bytesRead = 0;
+ enum xz_ret xz_rv = XZ_OK;
+ while (xz_rv == XZ_OK) {
+ if (strm.in_pos >= strm.in_size) {
+ size_t inlen = fread(inBuf, 1, FILE_BUFFER_SIZE, from);
+ if (inlen <= 0) {
+ rv = -1;
+ break;
+ }
+ bytesRead += inlen;
+ strm.in_size = inlen;
+ strm.in_pos = 0;
+ }
+
+ strm.out_pos = 0;
+ xz_rv = xz_dec_run(dec, &strm);
+ if (xz_rv != XZ_OK && xz_rv != XZ_STREAM_END) {
+ rv = -1;
+ break;
+ }
+
+ if (strm.out_pos != 0) {
+ if (fwrite(outBuf, strm.out_pos, 1, to) != 1) {
+ rv = -1;
+ break;
+ }
+ }
+ }
+
+ xz_dec_end(dec);
+ return rv;
+}
+
+static int
+mar_is_compressed(FILE* file)
+{
+ static const char XZ_MAGIC[] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
+ char buffer[sizeof(XZ_MAGIC)];
+ if (fread(buffer, sizeof(XZ_MAGIC), 1, file) != 1) {
+ return 0;
+ }
+ fseek(file, -(int)sizeof(XZ_MAGIC), SEEK_CUR);
+ return (memcmp(buffer, XZ_MAGIC, sizeof(XZ_MAGIC)) == 0) ? 1 : 0;
+}
+
+int
+mar_decompress(MarFile* file)
+{
+ int contentOffset = 0, contentLength = 0;
+ mar_get_content_extent(file, &contentOffset, &contentLength);
+
+ fseek(file->fp, contentOffset, SEEK_SET);
+
+ if (!mar_is_compressed(file->fp)) {
+ return 1;
+ }
+
+ // Create a temporary archive file.
+ NS_tchar extractedPath[MAXPATHLEN] = NS_T("");
+ int sprintfLen = NS_tsnprintf(extractedPath, MAXPATHLEN, NS_T("%s.extracted"), file->name);
+ // Make sure the path wasn't truncated before opening the file.
+ if (sprintfLen != NS_tstrlen(extractedPath)) {
+ return -1;
+ }
+ FILE * extractedFile = NS_tfopen(extractedPath, NS_T("wb+"));
+ if (!extractedFile) {
+ return -1;
+ }
+
+ // Copy from the archive file into the temp file, up to the content area.
+ int rv = 0;
+ int bytesRead = 0;
+ fseek(file->fp, 0, SEEK_SET);
+ while (bytesRead < contentOffset) {
+ int bytesToRead = FILE_BUFFER_SIZE;
+ if ((contentOffset - bytesRead) < FILE_BUFFER_SIZE) {
+ bytesToRead = contentOffset - bytesRead;
+ }
+ if (fread(inBuf, 1, bytesToRead, file->fp) == 0) {
+ rv = -1;
+ break;
+ }
+ bytesRead += bytesToRead;
+ if (fwrite(outBuf, bytesToRead, 1, extractedFile) != 1) {
+ rv = -1;
+ break;
+ }
+ }
+ if (rv) {
+ fclose(extractedFile);
+ NS_tremove(extractedPath);
+ return rv;
+ }
+
+ // Extract the compressed content into the temp file.
+ if (mar_decompress_xz_archive(file->fp, extractedFile) != 0) {
+ fclose(extractedFile);
+ NS_tremove(extractedPath);
+ return -1;
+ }
+
+ // Reset the file stream to the end of the content, because the extraction
+ // might have read past the end of the actual XZ stream.
+ fseek(file->fp, contentOffset + contentLength, SEEK_SET);
+
+ // Copy over the index from the MAR, which is all that's left past the content.
+ while (true) {
+ size_t bytesRead = fread(inBuf, 1, FILE_BUFFER_SIZE, file->fp);
+ if (bytesRead == 0) {
+ rv = feof(file->fp) ? 0 : -1;
+ break;
+ }
+ if (fwrite(outBuf, bytesRead, 1, extractedFile) != 1) {
+ rv = -1;
+ break;
+ }
+ }
+ if (rv) {
+ fclose(extractedFile);
+ NS_tremove(extractedPath);
+ return rv;
+ }
+
+ fclose(file->fp);
+ file->fp = extractedFile;
+ file->decompressed = true;
+ return 0;
+}
+
+void
+mar_decompress_cleanup(MarFile* file)
+{
+ NS_tchar extractedPath[MAXPATHLEN];
+ NS_tsnprintf(extractedPath, MAXPATHLEN, NS_T("%s.extracted"), file->name);
+ NS_tremove(extractedPath);
+}
--- a/modules/libmar/src/mar_extract.c
+++ b/modules/libmar/src/mar_extract.c
@@ -71,13 +71,18 @@ static int mar_test_callback(MarFile *ma
int mar_extract(const char *path) {
MarFile *mar;
int rv;
mar = mar_open(path);
if (!mar)
return -1;
+ if (mar_decompress(mar) < 0) {
+ mar_close(mar);
+ return -1;
+ }
+
rv = mar_enum_items(mar, mar_test_callback, NULL);
mar_close(mar);
return rv;
}
--- a/modules/libmar/src/mar_private.h
+++ b/modules/libmar/src/mar_private.h
@@ -2,16 +2,17 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MAR_PRIVATE_H__
#define MAR_PRIVATE_H__
+#include "mar.h"
#include "limits.h"
#include "mozilla/Assertions.h"
#include <stdint.h>
#define BLOCKSIZE 4096
#define ROUND_UP(n, incr) (((n) / (incr) + 1) * (incr))
#define MAR_ID "MAR1"
@@ -71,9 +72,16 @@ MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
(((((uint64_t) x) >> 16) & 0xFF) << 40) | \
(((((uint64_t) x) >> 24) & 0xFF) << 32) | \
(((((uint64_t) x) >> 32) & 0xFF) << 24) | \
(((((uint64_t) x) >> 40) & 0xFF) << 16) | \
(((((uint64_t) x) >> 48) & 0xFF) << 8) | \
(((uint64_t) x) >> 56)
#define NETWORK_TO_HOST64 HOST_TO_NETWORK64
+/**
+ * Clean up after mar_decompress().
+ * Should be called after the MarFile fp has been closed.
+ */
+void
+mar_decompress_cleanup(MarFile* file);
+
#endif /* MAR_PRIVATE_H__ */
--- a/modules/libmar/src/mar_read.c
+++ b/modules/libmar/src/mar_read.c
@@ -28,17 +28,17 @@ static uint32_t mar_hash_name(const char
return val % TABLESIZE;
}
static int mar_insert_item(MarFile *mar, const char *name, int namelen,
uint32_t offset, uint32_t length, uint32_t flags) {
MarItem *item, *root;
uint32_t hash;
-
+
item = (MarItem *) malloc(sizeof(MarItem) + namelen);
if (!item)
return -1;
item->next = NULL;
item->offset = offset;
item->length = length;
item->flags = flags;
memcpy(item->name, name, namelen + 1);
@@ -155,16 +155,17 @@ static MarFile *mar_fpopen(FILE *fp)
mar = (MarFile *) malloc(sizeof(*mar));
if (!mar) {
fclose(fp);
return NULL;
}
mar->fp = fp;
+ mar->decompressed = false;
memset(mar->item_table, 0, sizeof(mar->item_table));
if (mar_read_index(mar)) {
mar_close(mar);
return NULL;
}
return mar;
}
@@ -174,31 +175,46 @@ MarFile *mar_open(const char *path) {
fp = fopen(path, "rb");
if (!fp) {
fprintf(stderr, "ERROR: could not open file in mar_open()\n");
perror(path);
return NULL;
}
- return mar_fpopen(fp);
+ MarFile *rv = mar_fpopen(fp);
+ if (rv) {
+#ifdef XP_WIN
+ rv->name = malloc((strlen(path) + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, path, -1, rv->name, strlen(path) + 1);
+#else
+ rv->name = malloc(strlen(path));
+ strcpy(rv->name, path);
+#endif
+ }
+ return rv;
}
#ifdef XP_WIN
MarFile *mar_wopen(const wchar_t *path) {
FILE *fp;
_wfopen_s(&fp, path, L"rb");
if (!fp) {
fprintf(stderr, "ERROR: could not open file in mar_wopen()\n");
_wperror(path);
return NULL;
}
- return mar_fpopen(fp);
+ MarFile *rv = mar_fpopen(fp);
+ if (rv) {
+ rv->name = malloc(wcslen(path) * sizeof(wchar_t));
+ wcscpy(rv->name, path);
+ }
+ return rv;
}
#endif
void mar_close(MarFile *mar) {
MarItem *item;
int i;
fclose(mar->fp);
@@ -207,46 +223,51 @@ void mar_close(MarFile *mar) {
item = mar->item_table[i];
while (item) {
MarItem *temp = item;
item = item->next;
free(temp);
}
}
+ if (mar->decompressed) {
+ mar_decompress_cleanup(mar);
+ }
+
+ free(mar->name);
free(mar);
}
/**
* Determines the MAR file information.
*
* @param fp An opened MAR file in read mode.
* @param hasSignatureBlock Optional out parameter specifying if the MAR
* file has a signature block or not.
* @param numSignatures Optional out parameter for storing the number
* of signatures in the MAR file.
* @param hasAdditionalBlocks Optional out parameter specifying if the MAR
* file has additional blocks or not.
- * @param offsetAdditionalBlocks Optional out parameter for the offset to the
+ * @param offsetAdditionalBlocks Optional out parameter for the offset to the
* first additional block. Value is only valid if
* hasAdditionalBlocks is not equal to 0.
* @param numAdditionalBlocks Optional out parameter for the number of
* additional blocks. Value is only valid if
* hasAdditionalBlocks is not equal to 0.
* @return 0 on success and non-zero on failure.
*/
-int get_mar_file_info_fp(FILE *fp,
+int get_mar_file_info_fp(FILE *fp,
int *hasSignatureBlock,
uint32_t *numSignatures,
int *hasAdditionalBlocks,
uint32_t *offsetAdditionalBlocks,
uint32_t *numAdditionalBlocks)
{
uint32_t offsetToIndex, offsetToContent, signatureCount, signatureLen, i;
-
+
/* One of hasSignatureBlock or hasAdditionalBlocks must be non NULL */
if (!hasSignatureBlock && !hasAdditionalBlocks) {
return -1;
}
/* Skip to the start of the offset index */
if (fseek(fp, MAR_ID_SIZE, SEEK_SET)) {
@@ -267,18 +288,18 @@ int get_mar_file_info_fp(FILE *fp,
/* Read the number of signatures field */
if (fread(numSignatures, sizeof(*numSignatures), 1, fp) != 1) {
return -1;
}
*numSignatures = ntohl(*numSignatures);
}
- /* Skip to the first index entry past the index size field
- We do it in 2 calls because offsetToIndex + sizeof(uint32_t)
+ /* Skip to the first index entry past the index size field
+ We do it in 2 calls because offsetToIndex + sizeof(uint32_t)
could oerflow in theory. */
if (fseek(fp, offsetToIndex, SEEK_SET)) {
return -1;
}
if (fseek(fp, sizeof(uint32_t), SEEK_CUR)) {
return -1;
}
@@ -293,17 +314,17 @@ int get_mar_file_info_fp(FILE *fp,
if (hasSignatureBlock) {
if (offsetToContent == MAR_ID_SIZE + sizeof(uint32_t)) {
*hasSignatureBlock = 0;
} else {
*hasSignatureBlock = 1;
}
}
- /* If the caller doesn't care about the product info block
+ /* If the caller doesn't care about the product info block
value, then just return */
if (!hasAdditionalBlocks) {
return 0;
}
/* Skip to the start of the signature block */
if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
return -1;
@@ -348,102 +369,102 @@ int get_mar_file_info_fp(FILE *fp,
if (fread(numAdditionalBlocks, sizeof(uint32_t), 1, fp) != 1) {
return -1;
}
*numAdditionalBlocks = ntohl(*numAdditionalBlocks);
if (offsetAdditionalBlocks) {
*offsetAdditionalBlocks = ftell(fp);
}
} else if (offsetAdditionalBlocks) {
- /* numAdditionalBlocks is not specified but offsetAdditionalBlocks
+ /* numAdditionalBlocks is not specified but offsetAdditionalBlocks
is, so fill it! */
*offsetAdditionalBlocks = ftell(fp) + sizeof(uint32_t);
}
}
return 0;
}
-/**
+/**
* Reads the product info block from the MAR file's additional block section.
* The caller is responsible for freeing the fields in infoBlock
* if the return is successful.
*
* @param infoBlock Out parameter for where to store the result to
* @return 0 on success, -1 on failure
*/
int
-read_product_info_block(char *path,
+read_product_info_block(char *path,
struct ProductInformationBlock *infoBlock)
{
int rv;
MarFile mar;
mar.fp = fopen(path, "rb");
if (!mar.fp) {
fprintf(stderr, "ERROR: could not open file in read_product_info_block()\n");
perror(path);
return -1;
}
rv = mar_read_product_info_block(&mar, infoBlock);
fclose(mar.fp);
return rv;
}
-/**
+/**
* Reads the product info block from the MAR file's additional block section.
* The caller is responsible for freeing the fields in infoBlock
* if the return is successful.
*
* @param infoBlock Out parameter for where to store the result to
* @return 0 on success, -1 on failure
*/
int
-mar_read_product_info_block(MarFile *mar,
+mar_read_product_info_block(MarFile *mar,
struct ProductInformationBlock *infoBlock)
{
uint32_t i, offsetAdditionalBlocks, numAdditionalBlocks,
additionalBlockSize, additionalBlockID;
int hasAdditionalBlocks;
- /* The buffer size is 97 bytes because the MAR channel name < 64 bytes, and
+ /* The buffer size is 97 bytes because the MAR channel name < 64 bytes, and
product version < 32 bytes + 3 NULL terminator bytes. */
char buf[97] = { '\0' };
if (get_mar_file_info_fp(mar->fp, NULL, NULL,
&hasAdditionalBlocks,
&offsetAdditionalBlocks,
&numAdditionalBlocks) != 0) {
return -1;
}
for (i = 0; i < numAdditionalBlocks; ++i) {
/* Read the additional block size */
- if (fread(&additionalBlockSize,
- sizeof(additionalBlockSize),
+ if (fread(&additionalBlockSize,
+ sizeof(additionalBlockSize),
1, mar->fp) != 1) {
return -1;
}
- additionalBlockSize = ntohl(additionalBlockSize) -
- sizeof(additionalBlockSize) -
+ additionalBlockSize = ntohl(additionalBlockSize) -
+ sizeof(additionalBlockSize) -
sizeof(additionalBlockID);
/* Read the additional block ID */
- if (fread(&additionalBlockID,
- sizeof(additionalBlockID),
+ if (fread(&additionalBlockID,
+ sizeof(additionalBlockID),
1, mar->fp) != 1) {
return -1;
}
additionalBlockID = ntohl(additionalBlockID);
if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) {
const char *location;
int len;
/* This block must be at most 104 bytes.
- MAR channel name < 64 bytes, and product version < 32 bytes + 3 NULL
- terminator bytes. We only check for 96 though because we remove 8
- bytes above from the additionalBlockSize: We subtract
+ MAR channel name < 64 bytes, and product version < 32 bytes + 3 NULL
+ terminator bytes. We only check for 96 though because we remove 8
+ bytes above from the additionalBlockSize: We subtract
sizeof(additionalBlockSize) and sizeof(additionalBlockID) */
if (additionalBlockSize > 96) {
return -1;
}
if (fread(buf, additionalBlockSize, 1, mar->fp) != 1) {
return -1;
}
@@ -464,19 +485,19 @@ mar_read_product_info_block(MarFile *mar
len = strlen(location);
infoBlock->productVersion = location;
location += len + 1;
if (len >= 32) {
infoBlock->MARChannelID = NULL;
infoBlock->productVersion = NULL;
return -1;
}
- infoBlock->MARChannelID =
+ infoBlock->MARChannelID =
strdup(infoBlock->MARChannelID);
- infoBlock->productVersion =
+ infoBlock->productVersion =
strdup(infoBlock->productVersion);
return 0;
} else {
/* This is not the additional block you're looking for. Move along. */
if (fseek(mar->fp, additionalBlockSize, SEEK_CUR)) {
return -1;
}
}
@@ -540,38 +561,73 @@ int mar_read(MarFile *mar, const MarItem
*
* @param path The path of the MAR file to check.
* @param hasSignatureBlock Optional out parameter specifying if the MAR
* file has a signature block or not.
* @param numSignatures Optional out parameter for storing the number
* of signatures in the MAR file.
* @param hasAdditionalBlocks Optional out parameter specifying if the MAR
* file has additional blocks or not.
- * @param offsetAdditionalBlocks Optional out parameter for the offset to the
+ * @param offsetAdditionalBlocks Optional out parameter for the offset to the
* first additional block. Value is only valid if
* hasAdditionalBlocks is not equal to 0.
* @param numAdditionalBlocks Optional out parameter for the number of
* additional blocks. Value is only valid if
* has_additional_blocks is not equal to 0.
* @return 0 on success and non-zero on failure.
*/
-int get_mar_file_info(const char *path,
+int get_mar_file_info(const char *path,
int *hasSignatureBlock,
uint32_t *numSignatures,
int *hasAdditionalBlocks,
uint32_t *offsetAdditionalBlocks,
uint32_t *numAdditionalBlocks)
{
int rv;
FILE *fp = fopen(path, "rb");
if (!fp) {
fprintf(stderr, "ERROR: could not open file in get_mar_file_info()\n");
perror(path);
return -1;
}
- rv = get_mar_file_info_fp(fp, hasSignatureBlock,
+ rv = get_mar_file_info_fp(fp, hasSignatureBlock,
numSignatures, hasAdditionalBlocks,
offsetAdditionalBlocks, numAdditionalBlocks);
fclose(fp);
return rv;
}
+
+
+void
+mar_get_content_extent(MarFile* mar,
+ int* contentOffset,
+ int* contentLength)
+{
+ // Skip to the offset to index and read it.
+ uint32_t indexOffset;
+ if (fseek(mar->fp, MAR_ID_SIZE, SEEK_SET)) {
+ return;
+ }
+ if (fread(&indexOffset, sizeof(indexOffset), 1, mar->fp) != 1) {
+ return;
+ }
+ indexOffset = ntohl(indexOffset);
+
+ // Skip to the first index entry past the index size field.
+ // We do it in 2 calls because offsetToIndex + sizeof(uint32_t)
+ // could oerflow in theory.
+ if (fseek(mar->fp, indexOffset, SEEK_SET)) {
+ return;
+ }
+ if (fseek(mar->fp, sizeof(uint32_t), SEEK_CUR)) {
+ return;
+ }
+
+ // Read the first offset to content field, which will be the offset to the
+ // start of the content area since the index is always written in order.
+ if (fread(contentOffset, sizeof(*contentOffset), 1, mar->fp) != 1) {
+ return;
+ }
+ *contentOffset = ntohl(*contentOffset);
+ *contentLength = indexOffset - *contentOffset;
+}
--- a/modules/libmar/src/moz.build
+++ b/modules/libmar/src/moz.build
@@ -6,25 +6,31 @@
EXPORTS += [
'mar.h',
'mar_cmdline.h',
]
HOST_SOURCES += [
'mar_create.c',
+ 'mar_decompress.c',
'mar_extract.c',
'mar_read.c',
]
HostLibrary('hostmar')
Library('mar')
UNIFIED_SOURCES += [
'mar_create.c',
+ 'mar_decompress.c',
'mar_extract.c',
'mar_read.c',
]
+LOCAL_INCLUDES += [
+ '/toolkit/mozapps/update/common',
+]
+
FORCE_STATIC_LIB = True
if CONFIG['OS_ARCH'] == 'WINNT':
USE_STATIC_LIBS = True
--- a/modules/libmar/tool/moz.build
+++ b/modules/libmar/tool/moz.build
@@ -7,27 +7,29 @@
HOST_SOURCES += [
'mar.c',
]
HostProgram('mar')
HOST_USE_LIBS += [
'hostmar',
+ 'hostxz-embedded',
]
if CONFIG['MOZ_ENABLE_SIGNMAR']:
Program('signmar')
SOURCES += HOST_SOURCES
USE_LIBS += [
'mar',
'signmar',
'verifymar',
+ 'xz-embedded',
]
for var in ('MAR_CHANNEL_ID', 'MOZ_APP_VERSION'):
DEFINES[var] = '"%s"' % CONFIG[var]
HOST_DEFINES[var] = DEFINES[var]
if CONFIG['MOZ_ENABLE_SIGNMAR']:
USE_LIBS += [
--- a/modules/xz-embedded/moz.build
+++ b/modules/xz-embedded/moz.build
@@ -3,31 +3,44 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'src/xz.h',
]
-UNIFIED_SOURCES += [
+common_sources = [
'src/xz_crc32.c',
'src/xz_crc64.c',
'src/xz_dec_bcj.c',
'src/xz_dec_lzma2.c',
'src/xz_dec_stream.c',
]
+UNIFIED_SOURCES += common_sources
+
ALLOW_COMPILER_WARNINGS = True
if CONFIG['TARGET_CPU'].startswith('arm'):
# Accept arm, armv7, etc.
if CONFIG['MOZ_THUMB2']:
DEFINES['XZ_DEC_ARMTHUMB'] = 1
+ HOST_DEFINES['XZ_DEC_ARMTHUMB'] = 1
else:
DEFINES['XZ_DEC_ARM'] = 1
+ HOST_DEFINES['XZ_DEC_ARM'] = 1
elif '86' in CONFIG['TARGET_CPU']:
# Accept x86, x86_64, i386, i686, etc.
DEFINES['XZ_DEC_X86'] = 1
+ HOST_DEFINES['XZ_DEC_X86'] = 1
DEFINES['XZ_USE_CRC64'] = 1
+HOST_DEFINES['XZ_USE_CRC64'] = 1
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ USE_STATIC_LIBS = True
Library('xz-embedded')
+
+HOST_SOURCES += common_sources
+
+HostLibrary('hostxz-embedded')
--- a/toolkit/mozapps/update/common/errors.h
+++ b/toolkit/mozapps/update/common/errors.h
@@ -66,16 +66,18 @@
#define DELETE_ERROR_EXPECTED_FILE 47
#define RENAME_ERROR_EXPECTED_FILE 48
// Error codes 24-33 and 49-51 are for the Windows maintenance service.
#define SERVICE_COULD_NOT_COPY_UPDATER 49
#define SERVICE_STILL_APPLYING_TERMINATED 50
#define SERVICE_STILL_APPLYING_NO_EXIT_CODE 51
+#define UNEXPECTED_XZ_ERROR 52
+
#define WRITE_ERROR_FILE_COPY 61
#define WRITE_ERROR_DELETE_FILE 62
#define WRITE_ERROR_OPEN_PATCH_FILE 63
#define WRITE_ERROR_PATCH_FILE 64
#define WRITE_ERROR_APPLY_DIR_PATH 65
#define WRITE_ERROR_CALLBACK_PATH 66
#define WRITE_ERROR_FILE_ACCESS_DENIED 67
#define WRITE_ERROR_DIR_ACCESS_DENIED 68
--- a/toolkit/mozapps/update/common/readstrings.h
+++ b/toolkit/mozapps/update/common/readstrings.h
@@ -2,24 +2,19 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef READSTRINGS_H__
#define READSTRINGS_H__
-#define MAX_TEXT_LEN 600
+#include "updatedefines.h"
-#ifdef XP_WIN
-# include <windows.h>
- typedef WCHAR NS_tchar;
-#else
- typedef char NS_tchar;
-#endif
+#define MAX_TEXT_LEN 600
#ifndef NULL
#define NULL 0
#endif
struct StringTable
{
char title[MAX_TEXT_LEN];
--- a/toolkit/mozapps/update/common/updatedefines.h
+++ b/toolkit/mozapps/update/common/updatedefines.h
@@ -1,17 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef UPDATEDEFINES_H
#define UPDATEDEFINES_H
-#include "readstrings.h"
-
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# elif defined(MAX_PATH)
# define MAXPATHLEN MAX_PATH
# elif defined(_MAX_PATH)
# define MAXPATHLEN _MAX_PATH
# elif defined(CCHMAXPATH)
@@ -24,16 +22,18 @@
#if defined(XP_WIN)
# include <windows.h>
# include <shlwapi.h>
# include <direct.h>
# include <io.h>
# include <stdio.h>
# include <stdarg.h>
+typedef WCHAR NS_tchar;
+
# ifndef F_OK
# define F_OK 00
# endif
# ifndef W_OK
# define W_OK 02
# endif
# ifndef R_OK
# define R_OK 04
@@ -72,62 +72,72 @@ static inline int mywcsprintf(WCHAR* des
# define NS_tmkdir(path, perms) _wmkdir(path)
# define NS_tremove _wremove
// _wrename is used to avoid the link tracking service.
# define NS_trename _wrename
# define NS_trmdir _wrmdir
# define NS_tstat _wstat
# define NS_tlstat _wstat // No symlinks on Windows
# define NS_tstat_t _stat
+# define NS_tsystem _wsystem
# define NS_tstrcat wcscat
+# define NS_tstrncat wcsncat
# define NS_tstrcmp wcscmp
# define NS_tstricmp wcsicmp
# define NS_tstrcpy wcscpy
# define NS_tstrncpy wcsncpy
# define NS_tstrlen wcslen
# define NS_tstrchr wcschr
# define NS_tstrrchr wcsrchr
# define NS_tstrstr wcsstr
+
+#ifdef __cplusplus
# include "win_dirent.h"
# define NS_tDIR DIR
# define NS_tdirent dirent
# define NS_topendir opendir
# define NS_tclosedir closedir
# define NS_treaddir readdir
+#endif
+
#else
# include <sys/wait.h>
# include <unistd.h>
#ifdef SOLARIS
# include <sys/stat.h>
#else
# include <fts.h>
#endif
# include <dirent.h>
#ifdef XP_MACOSX
# include <sys/time.h>
#endif
+typedef char NS_tchar;
+
# define LOG_S "%s"
# define NS_T(str) str
# define NS_SLASH NS_T('/')
# define NS_tsnprintf snprintf
# define NS_taccess access
# define NS_tchdir chdir
# define NS_tchmod chmod
# define NS_tfopen fopen
# define NS_tmkdir mkdir
# define NS_tremove remove
# define NS_trename rename
# define NS_trmdir rmdir
# define NS_tstat stat
# define NS_tstat_t stat
# define NS_tlstat lstat
+# define NS_tsystem system
# define NS_tstrcat strcat
+# define NS_tstrncat strncat
# define NS_tstrcmp strcmp
# define NS_tstricmp strcasecmp
# define NS_tstrcpy strcpy
# define NS_tstrncpy strncpy
# define NS_tstrlen strlen
# define NS_tstrrchr strrchr
# define NS_tstrstr strstr
# define NS_tDIR DIR
--- a/toolkit/mozapps/update/updater/archivereader.cpp
+++ b/toolkit/mozapps/update/updater/archivereader.cpp
@@ -2,17 +2,16 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
-#include "bzlib.h"
#include "archivereader.h"
#include "errors.h"
#ifdef XP_WIN
#include "nsAlgorithm.h" // Needed by nsVersionComparator.cpp
#include "updatehelper.h"
#endif
// These are generated at compile time based on the DER file for the channel
@@ -266,59 +265,33 @@ ArchiveReader::ExtractFileToStream(const
return READ_ERROR;
return ExtractItemToStream(item, fp);
}
int
ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
{
- /* decompress the data chunk by chunk */
-
- bz_stream strm;
- int offset, inlen, outlen, ret = OK;
-
- memset(&strm, 0, sizeof(strm));
- if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK)
- return UNEXPECTED_BZIP_ERROR;
-
- offset = 0;
- for (;;) {
- if (!item->length) {
- ret = UNEXPECTED_MAR_ERROR;
- break;
- }
+ // We need to wait to do this until after the certificate has been checked,
+ // so that we don't do a bunch of processing on a file of unknown validity.
+ // At this point, the check has to have been done if it's going to be.
+ if (mar_decompress(mArchive) == -1) {
+ return UNEXPECTED_XZ_ERROR;
+ }
- if (offset < (int) item->length && strm.avail_in == 0) {
- inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size);
- if (inlen <= 0)
- return READ_ERROR;
- offset += inlen;
- strm.next_in = inbuf;
- strm.avail_in = inlen;
- }
-
- strm.next_out = outbuf;
- strm.avail_out = outbuf_size;
+ if (item->length == 0) {
+ return UNEXPECTED_MAR_ERROR;
+ }
- ret = BZ2_bzDecompress(&strm);
- if (ret != BZ_OK && ret != BZ_STREAM_END) {
- ret = UNEXPECTED_BZIP_ERROR;
- break;
+ int offset = 0;
+ while (offset < (int)(item->length)) {
+ int inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size);
+ if (inlen <= 0) {
+ return READ_ERROR;
}
-
- outlen = outbuf_size - strm.avail_out;
- if (outlen) {
- if (fwrite(outbuf, outlen, 1, fp) != 1) {
- ret = WRITE_ERROR_EXTRACT;
- break;
- }
- }
-
- if (ret == BZ_STREAM_END) {
- ret = OK;
- break;
+ offset += inlen;
+ if (fwrite(inbuf, inlen, 1, fp) != 1) {
+ return WRITE_ERROR_EXTRACT;
}
}
- BZ2_bzDecompressEnd(&strm);
- return ret;
+ return OK;
}
--- a/toolkit/mozapps/update/updater/archivereader.h
+++ b/toolkit/mozapps/update/updater/archivereader.h
@@ -6,19 +6,20 @@
#ifndef ArchiveReader_h__
#define ArchiveReader_h__
#include <stdio.h>
#include "mar.h"
#ifdef XP_WIN
- typedef WCHAR NS_tchar;
+#include <windows.h>
+typedef WCHAR NS_tchar;
#else
- typedef char NS_tchar;
+typedef char NS_tchar;
#endif
// This class provides an API to extract files from an update archive.
class ArchiveReader
{
public:
ArchiveReader() : mArchive(nullptr) {}
~ArchiveReader() { Close(); }
--- a/toolkit/mozapps/update/updater/updater-common.build
+++ b/toolkit/mozapps/update/updater/updater-common.build
@@ -53,25 +53,19 @@ elif CONFIG['OS_ARCH'] == 'Linux' and CO
OS_LIBS += CONFIG['NSPR_LIBS']
else:
USE_LIBS += [
'updatecommon',
]
USE_LIBS += [
'mar',
+ 'xz-embedded',
]
-if CONFIG['MOZ_SYSTEM_BZ2']:
- OS_LIBS += CONFIG['MOZ_BZ2_LIBS']
-else:
- USE_LIBS += [
- 'bz2',
- ]
-
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
have_progressui = 1
srcs += [
'progressui_gtk.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
have_progressui = 1
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -33,17 +33,17 @@
* -----------
* method = "remove" | "rmdir"
*/
#include "bspatch.h"
#include "progressui.h"
#include "archivereader.h"
#include "readstrings.h"
#include "errors.h"
-#include "bzlib.h"
+#include "xz.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -163,47 +163,16 @@ BOOL PathGetSiblingFilePath(LPWSTR desti
LogFinish(); \
return retCode; \
} \
}
#endif
//-----------------------------------------------------------------------------
-// This variable lives in libbz2. It's declared in bzlib_private.h, so we just
-// declare it here to avoid including that entire header file.
-#define BZ2_CRC32TABLE_UNDECLARED
-
-#if MOZ_IS_GCC || defined(__clang__)
-extern "C" __attribute__((visibility("default"))) unsigned int BZ2_crc32Table[256];
-#undef BZ2_CRC32TABLE_UNDECLARED
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-extern "C" __global unsigned int BZ2_crc32Table[256];
-#undef BZ2_CRC32TABLE_UNDECLARED
-#endif
-#if defined(BZ2_CRC32TABLE_UNDECLARED)
-extern "C" unsigned int BZ2_crc32Table[256];
-#undef BZ2_CRC32TABLE_UNDECLARED
-#endif
-
-static unsigned int
-crc32(const unsigned char *buf, unsigned int len)
-{
- unsigned int crc = 0xffffffffL;
-
- const unsigned char *end = buf + len;
- for (; buf != end; ++buf)
- crc = (crc << 8) ^ BZ2_crc32Table[(crc >> 24) ^ *buf];
-
- crc = ~crc;
- return crc;
-}
-
-//-----------------------------------------------------------------------------
-
// A simple stack based container for a FILE struct that closes the
// file descriptor from its destructor.
class AutoFile
{
public:
explicit AutoFile(FILE* file = nullptr)
: mFile(file) {
}
@@ -1545,19 +1514,17 @@ PatchFile::LoadSourceFile(FILE* ofile)
return READ_ERROR;
}
r -= c;
rb += c;
}
// Verify that the contents of the source file correspond to what we expect.
-
- unsigned int crc = crc32(buf, header.slen);
-
+ uint32_t crc = xz_crc32(buf, header.slen, 0);
if (crc != header.scrc32) {
LOG(("LoadSourceFile: destination file crc %d does not match expected " \
"crc %d", crc, header.scrc32));
return CRC_ERROR;
}
return OK;
}
--- a/tools/update-packaging/common.sh
+++ b/tools/update-packaging/common.sh
@@ -6,42 +6,30 @@
#
# Code shared by update packaging scripts.
# Author: Darin Fisher
#
# -----------------------------------------------------------------------------
# By default just assume that these tools exist on our path
MAR=${MAR:-mar}
-BZIP2=${BZIP2:-bzip2}
MBSDIFF=${MBSDIFF:-mbsdiff}
# -----------------------------------------------------------------------------
# Helper routines
notice() {
echo "$*" 1>&2
}
get_file_size() {
info=($(ls -ln "$1"))
echo ${info[4]}
}
-copy_perm() {
- reference="$1"
- target="$2"
-
- if [ -x "$reference" ]; then
- chmod 0755 "$target"
- else
- chmod 0644 "$target"
- fi
-}
-
make_add_instruction() {
f="$1"
filev2="$2"
# The third param will be an empty string when a file add instruction is only
# needed in the version 2 manifest. This only happens when the file has an
# add-if-not instruction in the version 3 manifest. This is due to the
# precomplete file prior to the version 3 manifest having a remove instruction
# for this file so the file is removed before applying a complete update.
--- a/tools/update-packaging/make_full_update.sh
+++ b/tools/update-packaging/make_full_update.sh
@@ -88,30 +88,26 @@ for ((i=0; $i<$num_files; i=$i+1)); do
make_add_instruction "$f" "$updatemanifestv2" "" 1
fi
else
make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
fi
dir=$(dirname "$f")
mkdir -p "$workdir/$dir"
- $BZIP2 -cz9 "$targetdir/$f" > "$workdir/$f"
- copy_perm "$targetdir/$f" "$workdir/$f"
+ cp -p "$targetdir/$f" "$workdir/$f"
targetfiles="$targetfiles \"$f\""
done
# Append remove instructions for any dead files.
notice ""
notice "Adding file and directory remove instructions from file 'removed-files'"
append_remove_instructions "$targetdir" "$updatemanifestv2" "$updatemanifestv3"
-$BZIP2 -z9 "$updatemanifestv2" && mv -f "$updatemanifestv2.bz2" "$updatemanifestv2"
-$BZIP2 -z9 "$updatemanifestv3" && mv -f "$updatemanifestv3.bz2" "$updatemanifestv3"
-
eval "$MAR -C \"$workdir\" -c output.mar $targetfiles"
mv -f "$workdir/output.mar" "$archive"
# cleanup
rm -fr "$workdir"
notice ""
notice "Finished"
--- a/tools/update-packaging/make_incremental_update.sh
+++ b/tools/update-packaging/make_incremental_update.sh
@@ -164,28 +164,26 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); d
f="${oldfiles[$i]}"
# If this file exists in the new directory as well, then check if it differs.
if [ -f "$newdir/$f" ]; then
if check_for_add_if_not_update "$f"; then
# The full workdir may not exist yet, so create it if necessary.
mkdir -p `dirname "$workdir/$f"`
- $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
- copy_perm "$newdir/$f" "$workdir/$f"
+ cp -p "$newdir/$f" "$workdir/$f"
make_add_if_not_instruction "$f" "$updatemanifestv3"
archivefiles="$archivefiles \"$f\""
continue 1
fi
if check_for_forced_update "$requested_forced_updates" "$f"; then
# The full workdir may not exist yet, so create it if necessary.
mkdir -p `dirname "$workdir/$f"`
- $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
- copy_perm "$newdir/$f" "$workdir/$f"
+ cp -p "$newdir/$f" "$workdir/$f"
make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" 1
archivefiles="$archivefiles \"$f\""
continue 1
fi
if ! diff "$olddir/$f" "$newdir/$f" > /dev/null; then
# Compute both the compressed binary diff and the compressed file, and
# compare the sizes. Then choose the smaller of the two to package.
@@ -202,31 +200,28 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); d
# myscript.sh -A SERVER-URL [-c LOCAL-CACHE-DIR-PATH] [-g] [-u] \
# PATH-FROM-URL PATH-TO-URL PATH-PATCH SERVER-URL
#
# Note: patches are bzipped stashed in funsize to gain more speed
# if service is not enabled then default to old behavior
if [ -z "$MBSDIFF_HOOK" ]; then
$MBSDIFF "$olddir/$f" "$newdir/$f" "$workdir/$f.patch"
- $BZIP2 -z9 "$workdir/$f.patch"
else
# if service enabled then check patch existence for retrieval
- if $MBSDIFF_HOOK -g "$olddir/$f" "$newdir/$f" "$workdir/$f.patch.bz2"; then
+ if $MBSDIFF_HOOK -g "$olddir/$f" "$newdir/$f" "$workdir/$f.patch"; then
notice "file \"$f\" found in funsize, diffing skipped"
else
# if not found already - compute it and cache it for future use
$MBSDIFF "$olddir/$f" "$newdir/$f" "$workdir/$f.patch"
- $BZIP2 -z9 "$workdir/$f.patch"
- $MBSDIFF_HOOK -u "$olddir/$f" "$newdir/$f" "$workdir/$f.patch.bz2"
+ $MBSDIFF_HOOK -u "$olddir/$f" "$newdir/$f" "$workdir/$f.patch"
fi
fi
- $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
- copy_perm "$newdir/$f" "$workdir/$f"
- patchfile="$workdir/$f.patch.bz2"
+ cp -p "$newdir/$f" "$workdir/$f"
+ patchfile="$workdir/$f.patch"
patchsize=$(get_file_size "$patchfile")
fullsize=$(get_file_size "$workdir/$f")
if [ $patchsize -lt $fullsize ]; then
make_patch_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
mv -f "$patchfile" "$workdir/$f.patch"
rm -f "$workdir/$f"
archivefiles="$archivefiles \"$f.patch\""
@@ -257,18 +252,17 @@ for ((i=0; $i<$num_newfiles; i=$i+1)); d
if [ "$f" = "${oldfiles[j]}" ]; then
continue 2
fi
done
dir=$(dirname "$workdir/$f")
mkdir -p "$dir"
- $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
- copy_perm "$newdir/$f" "$workdir/$f"
+ cp -p "$newdir/$f" "$workdir/$f"
if check_for_add_if_not_update "$f"; then
make_add_if_not_instruction "$f" "$updatemanifestv3"
else
make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
fi
@@ -298,19 +292,16 @@ for ((i=0; $i<$num_olddirs; i=$i+1)); do
# If this dir doesn't exist in the new directory remove it.
if [ ! -d "$newdir/$f" ]; then
notice " rmdir $f/"
echo "rmdir \"$f/\"" >> $updatemanifestv2
echo "rmdir \"$f/\"" >> $updatemanifestv3
fi
done
-$BZIP2 -z9 "$updatemanifestv2" && mv -f "$updatemanifestv2.bz2" "$updatemanifestv2"
-$BZIP2 -z9 "$updatemanifestv3" && mv -f "$updatemanifestv3.bz2" "$updatemanifestv3"
-
mar_command="$MAR"
if [[ -n $MOZ_PRODUCT_VERSION ]]
then
mar_command="$mar_command -V $MOZ_PRODUCT_VERSION"
fi
if [[ -n $MOZ_CHANNEL_ID ]]
then
mar_command="$mar_command -H $MOZ_CHANNEL_ID"