blob: 9b15f10e5bb5e6632dffe6ebf362ddb0055e0006 [file] [log] [blame]
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
Andrew de los Reyesd2135f32010-03-11 16:00:28 -08002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Andrew de los Reyesb10320d2010-03-31 16:44:44 -07005#include "update_engine/bzip.h"
Alex Deymoaab50e32014-11-10 19:55:35 -08006
Andrew de los Reyesd2135f32010-03-11 16:00:28 -08007#include <stdlib.h>
8#include <algorithm>
9#include <bzlib.h>
Alex Deymo914c4462015-06-26 17:17:05 -070010#include <limits>
11
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080012#include "update_engine/utils.h"
13
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080014using std::string;
15using std::vector;
16
17namespace chromeos_update_engine {
18
19namespace {
20
21// BzipData compresses or decompresses the input to the output.
22// Returns true on success.
23// Use one of BzipBuffToBuff*ompress as the template parameter to BzipData().
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080024int BzipBuffToBuffDecompress(uint8_t* out,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070025 uint32_t* out_length,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080026 const void* in,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070027 uint32_t in_length) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080028 return BZ2_bzBuffToBuffDecompress(
29 reinterpret_cast<char*>(out),
30 out_length,
31 reinterpret_cast<char*>(const_cast<void*>(in)),
32 in_length,
33 0, // Silent verbosity
34 0); // Normal algorithm
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080035}
36
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080037int BzipBuffToBuffCompress(uint8_t* out,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070038 uint32_t* out_length,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080039 const void* in,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070040 uint32_t in_length) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080041 return BZ2_bzBuffToBuffCompress(
42 reinterpret_cast<char*>(out),
43 out_length,
44 reinterpret_cast<char*>(const_cast<void*>(in)),
45 in_length,
46 9, // Best compression
47 0, // Silent verbosity
48 0); // Default work factor
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080049}
50
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080051template<int F(uint8_t* out,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070052 uint32_t* out_length,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080053 const void* in,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070054 uint32_t in_length)>
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080055bool BzipData(const void* const in,
Alex Deymo914c4462015-06-26 17:17:05 -070056 const size_t in_size,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080057 chromeos::Blob* const out) {
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080058 TEST_AND_RETURN_FALSE(out);
59 out->clear();
60 if (in_size == 0) {
61 return true;
62 }
63 // Try increasing buffer size until it works
64 size_t buf_size = in_size;
65 out->resize(buf_size);
Alex Vakulenkod2779df2014-06-16 13:19:00 -070066
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080067 for (;;) {
Alex Deymo914c4462015-06-26 17:17:05 -070068 if (buf_size > std::numeric_limits<uint32_t>::max())
69 return false;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070070 uint32_t data_size = buf_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080071 int rc = F(out->data(), &data_size, in, in_size);
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080072 TEST_AND_RETURN_FALSE(rc == BZ_OUTBUFF_FULL || rc == BZ_OK);
73 if (rc == BZ_OK) {
74 // we're done!
75 out->resize(data_size);
76 return true;
77 }
Alex Vakulenkod2779df2014-06-16 13:19:00 -070078
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080079 // Data didn't fit; double the buffer size.
80 buf_size *= 2;
81 out->resize(buf_size);
82 }
83}
84
Alex Vakulenkod2779df2014-06-16 13:19:00 -070085} // namespace
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080086
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080087bool BzipDecompress(const chromeos::Blob& in, chromeos::Blob* out) {
Alex Deymo914c4462015-06-26 17:17:05 -070088 return BzipData<BzipBuffToBuffDecompress>(in.data(), in.size(), out);
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080089}
90
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080091bool BzipCompress(const chromeos::Blob& in, chromeos::Blob* out) {
92 return BzipData<BzipBuffToBuffCompress>(in.data(), in.size(), out);
Andrew de los Reyesd2135f32010-03-11 16:00:28 -080093}
94
95namespace {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080096template<bool F(const void* const in,
Alex Deymo914c4462015-06-26 17:17:05 -070097 const size_t in_size,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080098 chromeos::Blob* const out)>
Alex Deymof329b932014-10-30 01:37:48 -070099bool BzipString(const string& str,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800100 chromeos::Blob* out) {
Andrew de los Reyesd2135f32010-03-11 16:00:28 -0800101 TEST_AND_RETURN_FALSE(out);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800102 chromeos::Blob temp;
103 TEST_AND_RETURN_FALSE(F(str.data(), str.size(), &temp));
Andrew de los Reyesd2135f32010-03-11 16:00:28 -0800104 out->clear();
105 out->insert(out->end(), temp.begin(), temp.end());
106 return true;
107}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700108} // namespace
Andrew de los Reyesd2135f32010-03-11 16:00:28 -0800109
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800110bool BzipCompressString(const string& str, chromeos::Blob* out) {
Ben Chanf9cb98c2014-09-21 18:31:30 -0700111 return BzipString<BzipData<BzipBuffToBuffCompress>>(str, out);
Andrew de los Reyesd2135f32010-03-11 16:00:28 -0800112}
113
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800114bool BzipDecompressString(const string& str, chromeos::Blob* out) {
Ben Chanf9cb98c2014-09-21 18:31:30 -0700115 return BzipString<BzipData<BzipBuffToBuffDecompress>>(str, out);
Andrew de los Reyesd2135f32010-03-11 16:00:28 -0800116}
117
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700118} // namespace chromeos_update_engine