Issue #1859 - Part 3: Replace bzip2 handling in MAR files with xz.

Since there really is no need to add file detection logic to the updater
if updating through AUS is old->new only anyway, replacing bzip2
handling with xz handling is fine, instead of adding it.
Considering the far superior compression of LZMA and MAR not being
a common archive format anyway, let's just K.I.S.S. it :)
This commit is contained in:
Moonchild 2022-01-20 18:10:55 +00:00 committed by roytam1
commit a195efca40
6 changed files with 64 additions and 37 deletions

View file

@ -109,7 +109,7 @@ int mar_enum_items(MarFile *mar, MarItemCallback callback, void *data);
* @return The number of bytes written or a negative value if an
* error occurs.
*/
int mar_read(MarFile *mar, const MarItem *item, int offset, char *buf,
int mar_read(MarFile *mar, const MarItem *item, int offset, uint8_t *buf,
int bufsize);
/**

View file

@ -37,7 +37,7 @@ static int mar_ensure_parent_dir(const char *path)
static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
FILE *fp;
char buf[BLOCKSIZE];
uint8_t buf[BLOCKSIZE];
int fd, len, offset = 0;
if (mar_ensure_parent_dir(item->name))

View file

@ -530,7 +530,7 @@ int mar_enum_items(MarFile *mar, MarItemCallback callback, void *closure) {
return 0;
}
int mar_read(MarFile *mar, const MarItem *item, int offset, char *buf,
int mar_read(MarFile *mar, const MarItem *item, int offset, uint8_t *buf,
int bufsize) {
int nr;

View file

@ -46,7 +46,7 @@
#define WRITE_ERROR_ACCESS_DENIED 35
// #define WRITE_ERROR_SHARING_VIOLATION 36 // Replaced with errors 46-48
#define WRITE_ERROR_CALLBACK_APP 37
#define UNEXPECTED_BZIP_ERROR 39
#define UNEXPECTED_XZ_ERROR 39
#define UNEXPECTED_MAR_ERROR 40
#define UNEXPECTED_BSPATCH_ERROR 41
#define UNEXPECTED_FILE_OPERATION_ERROR 42

View file

@ -1,5 +1,4 @@
/* -*- 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/. */
@ -15,6 +14,9 @@
#include "updatehelper.h"
#endif
#define XZ_USE_CRC64
#include "xz.h"
// These are generated at compile time based on the DER file for the channel
// being used
#ifdef MOZ_VERIFY_MAR_SIGNATURE
@ -36,10 +38,10 @@
# include <io.h>
#endif
static int inbuf_size = 262144;
static int outbuf_size = 262144;
static char *inbuf = nullptr;
static char *outbuf = nullptr;
static size_t inbuf_size = 262144;
static size_t outbuf_size = 262144;
static uint8_t *inbuf = nullptr;
static uint8_t *outbuf = nullptr;
/**
* Performs a verification on the opened MAR file with the passed in
@ -182,22 +184,22 @@ ArchiveReader::Open(const NS_tchar *path)
Close();
if (!inbuf) {
inbuf = (char *)malloc(inbuf_size);
inbuf = (uint8_t *)malloc(inbuf_size);
if (!inbuf) {
// Try again with a smaller buffer.
inbuf_size = 1024;
inbuf = (char *)malloc(inbuf_size);
inbuf = (uint8_t *)malloc(inbuf_size);
if (!inbuf)
return ARCHIVE_READER_MEM_ERROR;
}
}
if (!outbuf) {
outbuf = (char *)malloc(outbuf_size);
outbuf = (uint8_t *)malloc(outbuf_size);
if (!outbuf) {
// Try again with a smaller buffer.
outbuf_size = 1024;
outbuf = (char *)malloc(outbuf_size);
outbuf = (uint8_t *)malloc(outbuf_size);
if (!outbuf)
return ARCHIVE_READER_MEM_ERROR;
}
@ -211,6 +213,9 @@ ArchiveReader::Open(const NS_tchar *path)
if (!mArchive)
return READ_ERROR;
xz_crc32_init();
xz_crc64_init();
return OK;
}
@ -273,12 +278,21 @@ ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
{
/* decompress the data chunk by chunk */
bz_stream strm;
int offset, inlen, outlen, ret = OK;
int offset, inlen, ret = OK;
struct xz_buf strm = { 0 };
enum xz_ret xz_rv = XZ_OK;
memset(&strm, 0, sizeof(strm));
if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK)
return UNEXPECTED_BZIP_ERROR;
struct xz_dec * dec = xz_dec_init(XZ_DYNALLOC, 64 * 1024 * 1024);
if (!dec) {
return UNEXPECTED_XZ_ERROR;
}
strm.in = inbuf;
strm.in_pos = 0;
strm.in_size = 0;
strm.out = outbuf;
strm.out_pos = 0;
strm.out_size = outbuf_size;
offset = 0;
for (;;) {
@ -287,38 +301,50 @@ ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
break;
}
if (offset < (int) item->length && strm.avail_in == 0) {
if (offset < (int) item->length && strm.in_pos == strm.in_size) {
inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size);
if (inlen <= 0)
return READ_ERROR;
if (inlen <= 0) {
ret = READ_ERROR;
break;
}
offset += inlen;
strm.next_in = inbuf;
strm.avail_in = inlen;
strm.in_size = inlen;
strm.in_pos = 0;
}
strm.next_out = outbuf;
strm.avail_out = outbuf_size;
xz_rv = xz_dec_run(dec, &strm);
ret = BZ2_bzDecompress(&strm);
if (ret != BZ_OK && ret != BZ_STREAM_END) {
ret = UNEXPECTED_BZIP_ERROR;
break;
}
outlen = outbuf_size - strm.avail_out;
if (outlen) {
if (fwrite(outbuf, outlen, 1, fp) != 1) {
if (strm.out_pos == outbuf_size) {
if (fwrite(outbuf, 1, strm.out_pos, fp) != strm.out_pos) {
ret = WRITE_ERROR_EXTRACT;
break;
}
strm.out_pos = 0;
}
if (ret == BZ_STREAM_END) {
ret = OK;
if (xz_rv == XZ_OK) {
// There is still more data to decompress.
continue;
}
// The return value of xz_dec_run is not XZ_OK and if it isn't XZ_STREAM_END
// an error has occured.
if (xz_rv != XZ_STREAM_END) {
ret = UNEXPECTED_XZ_ERROR;
break;
}
// Write out the remainder of the decompressed data. In the case of
// strm.out_pos == 0 this is needed to create empty files included in the
// mar file.
if (fwrite(outbuf, 1, strm.out_pos, fp) != strm.out_pos) {
ret = WRITE_ERROR_EXTRACT;
}
break;
}
BZ2_bzDecompressEnd(&strm);
xz_dec_end(dec);
return ret;
}

View file

@ -57,6 +57,7 @@ else:
USE_LIBS += [
'mar',
'xz-embedded',
]
if CONFIG['MOZ_SYSTEM_BZ2']: