bzip.cc revision 246bf21fd0074a1897c28a7c4703c2223e6224b6
1//
2// Copyright (C) 2010 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/payload_generator/bzip.h"
18
19#include <bzlib.h>
20#include <stdlib.h>
21
22#include <algorithm>
23#include <limits>
24
25#include "update_engine/common/utils.h"
26
27namespace chromeos_update_engine {
28
29bool BzipCompress(const brillo::Blob& in, brillo::Blob* out) {
30  TEST_AND_RETURN_FALSE(out);
31  out->clear();
32  if (in.size() == 0)
33    return true;
34
35  // We expect a compression ratio of about 35% with bzip2, so we start with
36  // that much output space, which will then be doubled if needed.
37  size_t buf_size = 40 + in.size() * 35 / 100;
38  out->resize(buf_size);
39
40  // Try increasing buffer size until it works
41  for (;;) {
42    if (buf_size > std::numeric_limits<uint32_t>::max())
43      return false;
44    uint32_t data_size = buf_size;
45    int rc = BZ2_bzBuffToBuffCompress(
46        reinterpret_cast<char*>(out->data()),
47        &data_size,
48        reinterpret_cast<char*>(const_cast<uint8_t*>(in.data())),
49        in.size(),
50        9,   // Best compression
51        0,   // Silent verbosity
52        0);  // Default work factor
53    TEST_AND_RETURN_FALSE(rc == BZ_OUTBUFF_FULL || rc == BZ_OK);
54    if (rc == BZ_OK) {
55      // we're done!
56      out->resize(data_size);
57      return true;
58    }
59
60    // Data didn't fit; double the buffer size.
61    buf_size *= 2;
62    out->resize(buf_size);
63  }
64}
65
66}  // namespace chromeos_update_engine
67