Esempio n. 1
0
static SquashBZ2Stream*
squash_bz2_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) {
  int bz2_e = 0;
  SquashBZ2Stream* stream;

  assert (codec != NULL);
  assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS);

  stream = squash_malloc (sizeof (SquashBZ2Stream));
  squash_bz2_stream_init (stream, codec, stream_type, options, squash_bz2_stream_destroy);

  if (stream_type == SQUASH_STREAM_COMPRESS) {
    bz2_e = BZ2_bzCompressInit (&(stream->stream),
                                squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_LEVEL),
                                0,
                                squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_WORK_FACTOR));
  } else if (stream_type == SQUASH_STREAM_DECOMPRESS) {
    bz2_e = BZ2_bzDecompressInit (&(stream->stream),
                                  0,
                                  squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_SMALL));
  } else {
    squash_assert_unreachable();
  }

  if (bz2_e != BZ_OK) {
    /* We validate the params so OOM is really the only time this
       should happen, and that really shouldn't be happening here. */
    stream = squash_object_unref (stream);
  }

  return stream;
}
Esempio n. 2
0
static SquashStatus
squash_brotli_compress_stream (SquashStream* stream, SquashOperation operation) {
  SquashStatus res = SQUASH_FAILED;
  SquashBrotliStream* s = (SquashBrotliStream*) stream;

  brotli::BrotliParams params;
  params.mode = (brotli::BrotliParams::Mode) squash_codec_get_option_int_index (stream->codec, stream->options, SQUASH_BROTLI_OPT_MODE);
  params.enable_transforms = squash_codec_get_option_int_index (stream->codec, stream->options, SQUASH_BROTLI_OPT_ENABLE_TRANSFORMS);

  s->ctx.comp = new brotli::BrotliCompressor (params);
  s->ctx.comp->WriteStreamHeader ();

  int block_size;
  uint8_t* input_buffer = (uint8_t*) malloc (SQUASH_BROTLI_MAX_BLOCK_SIZE);
  uint8_t* output_buffer = (uint8_t*) malloc (SQUASH_BROTLI_MAX_OUT_SIZE);
  size_t output_size;

  if (input_buffer == NULL || output_buffer == NULL) {
    res = squash_error (SQUASH_MEMORY);
    goto cleanup;
  }

  while ((block_size = BrotliRead (s->in, input_buffer, SQUASH_BROTLI_MAX_BLOCK_SIZE)) != 0) {
    output_size = SQUASH_BROTLI_MAX_OUT_SIZE;
    s->ctx.comp->WriteMetaBlock (block_size, input_buffer, false, &output_size, output_buffer);
    if (BrotliWrite (s->out, output_buffer, output_size) != output_size) {
      res = SQUASH_FAILED;
      goto cleanup;
    }
  }

  output_size = SQUASH_BROTLI_MAX_OUT_SIZE;
  s->ctx.comp->WriteMetaBlock (block_size, input_buffer, true, &output_size, output_buffer);
  if (BrotliWrite (s->out, output_buffer, output_size) != output_size) {
    res = squash_error (SQUASH_FAILED);
    goto cleanup;
  }

  res = SQUASH_OK;

 cleanup:
  free (input_buffer);
  free (output_buffer);
  delete s->ctx.comp;
  s->ctx.comp = NULL;

  return res;
}
Esempio n. 3
0
static SquashLZ4FStream*
squash_lz4f_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) {
  SquashLZ4FStream* stream;
  LZ4F_errorCode_t ec;

  assert (codec != NULL);

  stream = (SquashLZ4FStream*) squash_malloc (sizeof (SquashLZ4FStream));
  if (SQUASH_UNLIKELY(stream == NULL))
    return (squash_error (SQUASH_MEMORY), NULL);

  squash_lz4f_stream_init (stream, codec, stream_type, options, squash_lz4f_stream_destroy);

  if (stream_type == SQUASH_STREAM_COMPRESS) {
    ec = LZ4F_createCompressionContext(&(stream->data.comp.ctx), LZ4F_VERSION);

    stream->data.comp.state = SQUASH_LZ4F_STATE_INIT;

    stream->data.comp.output_buffer = NULL;
    stream->data.comp.output_buffer_pos = 0;
    stream->data.comp.output_buffer_size = 0;

    stream->data.comp.input_buffer_size = 0;

    stream->data.comp.prefs = (LZ4F_preferences_t) {
      {
        (LZ4F_blockSizeID_t) squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_BLOCK_SIZE),
        blockLinked,
        squash_codec_get_option_bool_index (codec, options, SQUASH_LZ4F_OPT_CHECKSUM) ?
          contentChecksumEnabled :
          noContentChecksum,
      },
      squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_LEVEL)
    };
  } else {
    ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION);
  }

  if (SQUASH_UNLIKELY(LZ4F_isError (ec))) {
    squash_object_unref (stream);
    return (squash_error (SQUASH_FAILED), NULL);
  }

  return stream;
}
Esempio n. 4
0
static SquashStatus
squash_pithy_compress_buffer (SquashCodec* codec,
                              size_t* compressed_size,
                              uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)],
                              size_t uncompressed_size,
                              const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)],
                              SquashOptions* options) {
  const int level = squash_codec_get_option_int_index (codec, options, SQUASH_PITHY_OPT_LEVEL);
  *compressed_size = pithy_Compress ((const char*) uncompressed, uncompressed_size, (char*) compressed, *compressed_size, level);
  return (*compressed_size != 0) ? SQUASH_OK : SQUASH_FAILED;
}
Esempio n. 5
0
static SquashStatus
squash_bz2_compress_buffer (SquashCodec* codec,
                            size_t* compressed_length,
                            uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                            size_t uncompressed_length,
                            const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                            SquashOptions* options) {
  int bz2_res;
  unsigned int compressed_length_ui = (unsigned int) *compressed_length;

  bz2_res = BZ2_bzBuffToBuffCompress ((char*) compressed, &compressed_length_ui,
                                      (char*) uncompressed, (unsigned int) uncompressed_length,
                                      squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_LEVEL),
                                      0,
                                      squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_WORK_FACTOR));
  if (bz2_res == BZ_OK) {
    *compressed_length = compressed_length_ui;
  }

  return squash_bz2_status_to_squash_status (bz2_res);
}
Esempio n. 6
0
static SquashStatus
squash_brotli_compress_buffer (SquashCodec* codec,
                               size_t* compressed_length,
                               uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                               size_t uncompressed_length,
                               const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                               SquashOptions* options) {
  brotli::BrotliParams params;
  params.mode = (brotli::BrotliParams::Mode) squash_codec_get_option_int_index (codec, options, SQUASH_BROTLI_OPT_MODE);
  params.enable_transforms = squash_codec_get_option_int_index (codec, options, SQUASH_BROTLI_OPT_ENABLE_TRANSFORMS);

  try {
    int res = brotli::BrotliCompressBuffer (params,
                                            uncompressed_length, uncompressed,
                                            compressed_length, compressed);
    return (res == 1) ? SQUASH_OK : SQUASH_FAILED;
  } catch (const std::bad_alloc& e) {
    return SQUASH_MEMORY;
  } catch (...) {
    return SQUASH_FAILED;
  }
}
Esempio n. 7
0
static SquashStatus
squash_fastlz_compress_buffer (SquashCodec* codec,
                               size_t* compressed_length,
                               uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                               size_t uncompressed_length,
                               const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                               SquashOptions* options) {
  *compressed_length = fastlz_compress_level (squash_codec_get_option_int_index (codec, options, SQUASH_FASTLZ_OPT_LEVEL),
                                              (const void*) uncompressed,
                                              (int) uncompressed_length,
                                              (void*) compressed);

  return (*compressed_length == 0) ? squash_error (SQUASH_FAILED) : SQUASH_OK;
}
Esempio n. 8
0
static void
squash_lz4f_stream_init (SquashLZ4FStream* stream,
                         SquashCodec* codec,
                         SquashStreamType stream_type,
                         SquashOptions* options,
                         SquashDestroyNotify destroy_notify) {
  LZ4F_errorCode_t ec;
  squash_stream_init ((SquashStream*) stream, codec, stream_type, (SquashOptions*) options, destroy_notify);

  if (stream_type == SQUASH_STREAM_COMPRESS) {
    ec = LZ4F_createCompressionContext(&(stream->data.comp.ctx), LZ4F_VERSION);

    stream->data.comp.state = SQUASH_LZ4F_STATE_INIT;

    stream->data.comp.output_buffer = NULL;
    stream->data.comp.output_buffer_pos = 0;
    stream->data.comp.output_buffer_length = 0;

    stream->data.comp.input_buffer_length = 0;

    stream->data.comp.prefs = (LZ4F_preferences_t) {
      {
        squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_BLOCK_SIZE),
        blockLinked,
        squash_codec_get_option_bool_index (codec, options, SQUASH_LZ4F_OPT_CHECKSUM) ?
          contentChecksumEnabled :
          noContentChecksum,
      },
      squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_LEVEL)
    };
  } else {
    ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION);
  }

  assert (!LZ4F_isError (ec));
}
Esempio n. 9
0
static SquashStatus
squash_lz4_compress_buffer (SquashCodec* codec,
                            size_t* compressed_size,
                            uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)],
                            size_t uncompressed_size,
                            const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)],
                            SquashOptions* options) {
  int level = squash_codec_get_option_int_index (codec, options, SQUASH_LZ4_OPT_LEVEL);

#if INT_MAX < SIZE_MAX
  if (SQUASH_UNLIKELY(INT_MAX < uncompressed_size) ||
      SQUASH_UNLIKELY(INT_MAX < *compressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  int lz4_r;

  if (level == 7) {
    lz4_r = LZ4_compress_limitedOutput ((char*) uncompressed,
                                        (char*) compressed,
                                        (int) uncompressed_size,
                                        (int) *compressed_size);
  } else if (level < 7) {
    lz4_r = LZ4_compress_fast ((const char*) uncompressed,
                               (char*) compressed,
                               (int) uncompressed_size,
                               (int) *compressed_size,
                               squash_lz4_level_to_fast_mode (level));
  } else if (level < 17) {
    lz4_r = LZ4_compressHC2_limitedOutput ((char*) uncompressed,
                                           (char*) compressed,
                                           (int) uncompressed_size,
                                           (int) *compressed_size,
                                           squash_lz4_level_to_hc_level (level));
  } else {
    squash_assert_unreachable();
  }

#if SIZE_MAX < INT_MAX
  if (SQUASH_UNLIKELY(SIZE_MAX < lz4_r))
    return squash_error (SQUASH_RANGE);
#endif

  *compressed_size = lz4_r;

  return SQUASH_UNLIKELY(lz4_r == 0) ? squash_error (SQUASH_BUFFER_FULL) : SQUASH_OK;
}
Esempio n. 10
0
static size_t
squash_lz4f_get_input_buffer_size (SquashStream* stream) {
  return squash_lz4f_block_size_id_to_size ((LZ4F_blockSizeID_t) squash_codec_get_option_int_index (stream->codec, stream->options, SQUASH_LZ4F_OPT_BLOCK_SIZE));
}
Esempio n. 11
0
static SquashStatus
squash_density_process_stream (SquashStream* stream, SquashOperation operation) {
  SquashDensityStream* s = (SquashDensityStream*) stream;

  if (s->buffer_size > 0) {
    squash_density_flush_internal_buffer (stream);
    return SQUASH_PROCESSING;
  }

  if (s->next == SQUASH_DENSITY_ACTION_INIT) {
    s->active_input_size = (stream->stream_type == SQUASH_STREAM_COMPRESS) ? ((stream->avail_in / SQUASH_DENSITY_INPUT_MULTIPLE) * SQUASH_DENSITY_INPUT_MULTIPLE) : stream->avail_in;
    if (stream->avail_out < DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE) {
      s->buffer_active = true;
      s->state = density_stream_prepare (s->stream, (uint8_t*) stream->next_in, s->active_input_size, s->buffer, DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE);
    } else {
      s->buffer_active = false;
      s->state = density_stream_prepare (s->stream, (uint8_t*) stream->next_in, s->active_input_size, stream->next_out, stream->avail_out);
    }
    if (SQUASH_UNLIKELY(s->state != DENSITY_STREAM_STATE_READY))
      return squash_error (SQUASH_FAILED);
  }

  switch (s->state) {
    case DENSITY_STREAM_STATE_STALL_ON_INPUT:
      if (s->input_buffer_size != 0 ||
          (stream->avail_in < SQUASH_DENSITY_INPUT_MULTIPLE && stream->stream_type == SQUASH_STREAM_COMPRESS && operation == SQUASH_OPERATION_PROCESS)) {
        const size_t remaining = SQUASH_DENSITY_INPUT_MULTIPLE - s->input_buffer_size;
        const size_t cp_size = remaining < stream->avail_in ? remaining : stream->avail_in;
        if (cp_size != 0) {
          memcpy (s->input_buffer + s->input_buffer_size, stream->next_in, cp_size);
          s->input_buffer_size += cp_size;
          stream->next_in += cp_size;
          stream->avail_in -= cp_size;
          assert (cp_size != 0);
        }
      }

      if (s->input_buffer_size != 0) {
        if (s->input_buffer_size == SQUASH_DENSITY_INPUT_MULTIPLE || operation != SQUASH_OPERATION_PROCESS) {
          s->active_input_size = s->input_buffer_size;
          s->input_buffer_active = true;
          density_stream_update_input (s->stream, s->input_buffer, s->input_buffer_size);
          s->state = DENSITY_STREAM_STATE_READY;
        } else {
          assert (stream->avail_in == 0);
          return SQUASH_OK;
        }
      } else {
        s->active_input_size = (stream->stream_type == SQUASH_STREAM_COMPRESS) ? ((stream->avail_in / SQUASH_DENSITY_INPUT_MULTIPLE) * SQUASH_DENSITY_INPUT_MULTIPLE) : stream->avail_in;
        density_stream_update_input (s->stream, stream->next_in, s->active_input_size);
        s->state = DENSITY_STREAM_STATE_READY;
      }
      break;
    case DENSITY_STREAM_STATE_STALL_ON_OUTPUT:
      {
        if (!s->output_invalid) {
          const size_t written = density_stream_output_available_for_use (s->stream);
          total_bytes_written += written;

          if (s->buffer_active) {
            s->buffer_size = written;
            s->buffer_pos = 0;

            const size_t cp_size = s->buffer_size < stream->avail_out ? s->buffer_size : stream->avail_out;
            memcpy (stream->next_out, s->buffer, cp_size);
            stream->next_out += cp_size;
            stream->avail_out -= cp_size;
            s->buffer_pos += cp_size;
            if (s->buffer_pos == s->buffer_size) {
              s->buffer_pos = 0;
              s->buffer_size = 0;
            }
          } else {
            assert (written <= stream->avail_out);
            stream->next_out += written;
            stream->avail_out -= written;
          }

          s->output_invalid = true;
          return SQUASH_PROCESSING;
        } else {
          if (stream->avail_out < DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE) {
            s->buffer_active = true;
            density_stream_update_output (s->stream, s->buffer, DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE);
          } else {
            s->buffer_active = false;
            density_stream_update_output (s->stream, stream->next_out, stream->avail_out);
          }
          s->output_invalid = false;
          s->state = DENSITY_STREAM_STATE_READY;
        }
      }
      break;
    case DENSITY_STREAM_STATE_READY:
      break;
    case DENSITY_STREAM_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL:
    case DENSITY_STREAM_STATE_ERROR_INVALID_INTERNAL_STATE:
    case DENSITY_STREAM_STATE_ERROR_INTEGRITY_CHECK_FAIL:
      return squash_error (SQUASH_FAILED);
  }

  assert (s->output_invalid == false);

  while (s->state == DENSITY_STREAM_STATE_READY && s->next != SQUASH_DENSITY_ACTION_FINISHED) {
    switch (s->next) {
      case SQUASH_DENSITY_ACTION_INIT:
        if (stream->stream_type == SQUASH_STREAM_COMPRESS) {
          DENSITY_COMPRESSION_MODE compression_mode =
            squash_density_level_to_mode (squash_codec_get_option_int_index (stream->codec, stream->options, SQUASH_DENSITY_OPT_LEVEL));
          DENSITY_BLOCK_TYPE block_type =
            squash_codec_get_option_bool_index (stream->codec, stream->options, SQUASH_DENSITY_OPT_CHECKSUM) ?
              DENSITY_BLOCK_TYPE_WITH_HASHSUM_INTEGRITY_CHECK :
              DENSITY_BLOCK_TYPE_DEFAULT;

          s->state = density_stream_compress_init (s->stream, compression_mode, block_type);
        } else {
          s->state = density_stream_decompress_init (s->stream, NULL);
        }
        if (SQUASH_UNLIKELY(s->state != DENSITY_STREAM_STATE_READY))
          return squash_error (SQUASH_FAILED);
        s->next = SQUASH_DENSITY_ACTION_CONTINUE;
        break;
      case SQUASH_DENSITY_ACTION_CONTINUE_OR_FINISH:
        s->next = (operation == SQUASH_OPERATION_PROCESS) ? SQUASH_DENSITY_ACTION_CONTINUE : SQUASH_DENSITY_ACTION_FINISH;
        break;
      case SQUASH_DENSITY_ACTION_CONTINUE:
        if (stream->stream_type == SQUASH_STREAM_COMPRESS) {
          s->state = density_stream_compress_continue (s->stream);
        } else {
          s->state = density_stream_decompress_continue (s->stream);
        }

        if (s->state == DENSITY_STREAM_STATE_STALL_ON_INPUT)
          s->next = SQUASH_DENSITY_ACTION_CONTINUE_OR_FINISH;

        break;
      case SQUASH_DENSITY_ACTION_FINISH:
        if (stream->stream_type == SQUASH_STREAM_COMPRESS) {
          s->state = density_stream_compress_finish (s->stream);
        } else {
          s->state = density_stream_decompress_finish (s->stream);
        }
        if (s->state == DENSITY_STREAM_STATE_READY) {
          s->state = DENSITY_STREAM_STATE_STALL_ON_OUTPUT;
          s->output_invalid = false;
          s->next = SQUASH_DENSITY_ACTION_FINISHED;
        }
        break;
      case SQUASH_DENSITY_ACTION_FINISHED:
      default:
        squash_assert_unreachable();
        break;
    }
  }

  if (s->state == DENSITY_STREAM_STATE_STALL_ON_INPUT) {
    if (s->input_buffer_active) {
      assert (s->active_input_size == s->input_buffer_size);
      s->input_buffer_active = false;
      s->input_buffer_size = 0;
    } else {
      assert (s->active_input_size <= stream->avail_in);
      stream->next_in += s->active_input_size;
      stream->avail_in -= s->active_input_size;
    }
    s->active_input_size = 0;
  } else if (s->state == DENSITY_STREAM_STATE_STALL_ON_OUTPUT) {
    {
      if (!s->output_invalid) {
        const size_t written = density_stream_output_available_for_use (s->stream);
        total_bytes_written += written;

        if (s->buffer_active) {
          s->buffer_size = written;
          s->buffer_pos = 0;

          const size_t cp_size = s->buffer_size < stream->avail_out ? s->buffer_size : stream->avail_out;
          memcpy (stream->next_out, s->buffer, cp_size);
          stream->next_out += cp_size;
          stream->avail_out -= cp_size;
          s->buffer_pos += cp_size;
          if (s->buffer_pos == s->buffer_size) {
            s->buffer_pos = 0;
            s->buffer_size = 0;
          }
        } else {
          assert (written <= stream->avail_out);
          stream->next_out += written;
          stream->avail_out -= written;
        }

        s->output_invalid = true;
        return SQUASH_PROCESSING;
      } else {
        squash_assert_unreachable();
      }
    }
  }

  if (operation == SQUASH_OPERATION_FINISH)
    total_bytes_written = 0;

  if (stream->avail_in == 0) {
    return SQUASH_OK;
  } else {
    return SQUASH_PROCESSING;
  }
}