Beispiel #1
0
static SquashStatus
squash_yalz77_decompress_buffer (SquashCodec* codec,
                                 size_t* decompressed_size,
                                 uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                                 size_t compressed_size,
                                 const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                                 SquashOptions* options) {
  try {
    lz77::decompress_t decompress(*decompressed_size);
    std::string remaining;
    bool done = decompress.feed(compressed, compressed + compressed_size, remaining);
    const std::string& res = decompress.result();

    memcpy(decompressed, res.c_str(), res.size());
    *decompressed_size = res.size();
    return (done && remaining.empty()) ? SQUASH_OK : SQUASH_FAILED;
  } catch (std::length_error& e) {
    (void) e;
    return squash_error (SQUASH_BUFFER_FULL);
  } catch (const std::bad_alloc& e) {
    (void) e;
    return squash_error (SQUASH_MEMORY);
  } catch (...) {
    return squash_error (SQUASH_FAILED);
  }
}
Beispiel #2
0
static SquashStatus
squash_lzg_decompress_buffer (SquashCodec* codec,
                              size_t* decompressed_size,
                              uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                              size_t compressed_size,
                              const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                              SquashOptions* options) {
  lzg_uint32_t res;

#if UINT32_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(UINT32_MAX < compressed_size) ||
      HEDLEY_UNLIKELY(UINT32_MAX < *decompressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  if (LZG_DecodedSize ((const unsigned char*) compressed, (lzg_uint32_t) compressed_size) > *decompressed_size)
    return squash_error (SQUASH_BUFFER_FULL);

  res = LZG_Decode ((const unsigned char*) compressed, (lzg_uint32_t) compressed_size,
                    (unsigned char*) decompressed, (lzg_uint32_t) *decompressed_size);

  if (HEDLEY_UNLIKELY(res == 0)) {
    return squash_error (SQUASH_FAILED);
  } else {
#if SIZE_MAX < UINT32_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < res))
      return squash_error (SQUASH_RANGE);
#endif
    *decompressed_size = (size_t) res;
    return SQUASH_OK;
  }
}
Beispiel #3
0
static SquashStatus
squash_libdeflate_decompress_buffer (SquashCodec* codec,
                                size_t* decompressed_size,
                                uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                                size_t compressed_size,
                                const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                                SquashOptions* options) {
  struct deflate_decompressor *decompressor = deflate_alloc_decompressor();
  size_t actual_out_nbytes;
  enum decompress_result ret = deflate_decompress(decompressor, compressed, compressed_size,
                                             decompressed, *decompressed_size, &actual_out_nbytes);
  deflate_free_decompressor(decompressor);
  *decompressed_size = actual_out_nbytes;
  switch (ret) {
    case DECOMPRESS_SUCCESS:
      return SQUASH_OK;
    case DECOMPRESS_BAD_DATA:
      return squash_error (SQUASH_FAILED);
    case DECOMPRESS_SHORT_OUTPUT:
      return squash_error (SQUASH_BUFFER_FULL);
    case DECOMPRESS_INSUFFICIENT_SPACE:
      return squash_error (SQUASH_BUFFER_FULL);
  }

  HEDLEY_UNREACHABLE ();
}
Beispiel #4
0
static SquashStatus
squash_yalz77_compress_buffer (SquashCodec* codec,
                               size_t* compressed_size,
                               uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                               size_t uncompressed_size,
                               const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                               SquashOptions* options) {

  const size_t searchlen = squash_options_get_size_at (options, codec, SQUASH_YALZ77_OPT_SEARCH_LENGTH);
  const size_t blocksize = squash_options_get_size_at (options, codec, SQUASH_YALZ77_OPT_BLOCK_SIZE);

  try {
    lz77::compress_t compress(searchlen, blocksize);
    std::string res = compress.feed(uncompressed, uncompressed + uncompressed_size);

    if (HEDLEY_UNLIKELY(res.size() > *compressed_size))
      return squash_error (SQUASH_BUFFER_FULL);

    memcpy(compressed, res.c_str(), res.size());
    *compressed_size = res.size();
    return SQUASH_OK;
  } catch (const std::bad_alloc& e) {
    (void) e;
    return squash_error (SQUASH_MEMORY);
  } catch (...) {
    return squash_error (SQUASH_FAILED);
  }
}
Beispiel #5
0
static SquashStatus
squash_fastlz_compress_buffer (SquashCodec* codec,
                               size_t* compressed_size,
                               uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                               size_t uncompressed_size,
                               const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                               SquashOptions* options) {
#if INT_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(INT_MAX < uncompressed_size) ||
      HEDLEY_UNLIKELY(INT_MAX < *compressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  const int fastlz_e =
    fastlz_compress_level (squash_options_get_int_at (options, codec, SQUASH_FASTLZ_OPT_LEVEL),
                           (const void*) uncompressed,
                           (int) uncompressed_size,
                           (void*) compressed);

#if SIZE_MAX < INT_MAX
  if (HEDLEY_UNLIKELY(SIZE_MAX < fastlz_e))
    return squash_error (SQUASH_RANGE);
#endif

  *compressed_size = (size_t) fastlz_e;

  return HEDLEY_UNLIKELY(fastlz_e == 0) ? squash_error (SQUASH_FAILED) : SQUASH_OK;
}
Beispiel #6
0
static SquashStatus
squash_fastlz_decompress_buffer (SquashCodec* codec,
                                 size_t* decompressed_size,
                                 uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                                 size_t compressed_size,
                                 const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                                 SquashOptions* options) {
#if INT_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(INT_MAX < compressed_size) ||
      HEDLEY_UNLIKELY(INT_MAX < *decompressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  int fastlz_e = fastlz_decompress ((const void*) compressed,
                                    (int) compressed_size,
                                    (void*) decompressed,
                                    (int) *decompressed_size);

  if (HEDLEY_UNLIKELY(fastlz_e < 0)) {
    return squash_error (SQUASH_FAILED);
  } else if (HEDLEY_UNLIKELY(fastlz_e == 0)) {
    return SQUASH_BUFFER_FULL;
  } else {
#if SIZE_MAX < INT_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < fastlz_e))
      return squash_error (SQUASH_RANGE);
#endif
    *decompressed_size = (size_t) fastlz_e;
    return SQUASH_OK;
  }
}
Beispiel #7
0
static SquashStatus
squash_brieflz_decompress_buffer (SquashCodec* codec,
                                  size_t* decompressed_size,
                                  uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                                  size_t compressed_size,
                                  const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                                  SquashOptions* options) {
    const uint8_t *src = compressed;
    unsigned long size;

#if ULONG_MAX < SIZE_MAX
    if (HEDLEY_UNLIKELY(ULONG_MAX < compressed_size) ||
            HEDLEY_UNLIKELY(ULONG_MAX < *decompressed_size))
        return squash_error (SQUASH_RANGE);
#endif

    size = blz_depack_safe (src, (unsigned long) compressed_size,
                            decompressed, (unsigned long) *decompressed_size);

    if (HEDLEY_UNLIKELY(size != *decompressed_size))
        return squash_error (SQUASH_FAILED);

#if SIZE_MAX < ULONG_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < size))
        return squash_error (SQUASH_RANGE);
#endif

    *decompressed_size = (size_t) size;

    return SQUASH_OK;
}
Beispiel #8
0
static SquashStatus
squash_libdeflate_compress_buffer (SquashCodec* codec,
                              size_t* compressed_size,
                              uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                              size_t uncompressed_size,
                              const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                              SquashOptions* options) {
  const int level = squash_options_get_int_at (options, codec, SQUASH_LIBDEFLATE_OPT_LEVEL);
  struct deflate_compressor *compressor = deflate_alloc_compressor(level);
  *compressed_size = deflate_compress(compressor, uncompressed, uncompressed_size, compressed, *compressed_size);
  deflate_free_compressor(compressor);
  return HEDLEY_LIKELY(*compressed_size != 0) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL);
}
Beispiel #9
0
static SquashStatus
squash_brieflz_compress_buffer (SquashCodec* codec,
                                size_t* compressed_size,
                                uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                                size_t uncompressed_size,
                                const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                                SquashOptions* options) {
    uint8_t *dst = compressed;
    void *workmem = NULL;
    unsigned long size;

#if ULONG_MAX < SIZE_MAX
    if (HEDLEY_UNLIKELY(ULONG_MAX < uncompressed_size) ||
            HEDLEY_UNLIKELY(ULONG_MAX < *compressed_size))
        return squash_error (SQUASH_RANGE);
#endif

    if (HEDLEY_UNLIKELY((unsigned long) *compressed_size
                        < squash_brieflz_get_max_compressed_size (codec, uncompressed_size))) {
        return squash_error (SQUASH_BUFFER_FULL);
    }

    workmem = squash_malloc (blz_workmem_size ((unsigned long) uncompressed_size));

    if (HEDLEY_UNLIKELY(workmem == NULL)) {
        return squash_error (SQUASH_MEMORY);
    }

    size = blz_pack (uncompressed, dst,
                     (unsigned long) uncompressed_size,
                     workmem);

    squash_free (workmem);

#if SIZE_MAX < ULONG_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < size))
        return squash_error (SQUASH_RANGE);
#endif

    *compressed_size = (size_t) size;

    return SQUASH_OK;
}
Beispiel #10
0
/**
 * @brief Write data to a compressed file
 *
 * Attempt to write the compressed equivalent of @a uncompressed to a
 * file.  The number of bytes of compressed data written to the output
 * file may be **significantly** more, or less, than the @a
 * uncompressed_size.
 *
 * @note It is likely the compressed data will actually be buffered,
 * not immediately written to the file.  For codecs which support
 * flushing you can use @ref squash_file_flush to flush the data,
 * otherwise the data may not be written until @ref squash_file_close
 * or @ref squash_file_free is called.
 *
 * @param file file to write to
 * @param uncompressed_size number of bytes of uncompressed data in
 *   @a uncompressed to attempt to write
 * @param uncompressed data to write
 * @return result of the operation
 */
SquashStatus
squash_file_write (SquashFile* file,
                   size_t uncompressed_size,
                   const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)]) {
  squash_file_lock (file);
  SquashStatus res = squash_file_write_unlocked (file, uncompressed_size, uncompressed);
  squash_file_unlock (file);

  return res;
}
Beispiel #11
0
static SquashStatus
squash_lzg_compress_buffer (SquashCodec* codec,
                            size_t* compressed_size,
                            uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                            size_t uncompressed_size,
                            const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                            SquashOptions* options) {
  lzg_encoder_config_t cfg = {
    squash_options_get_int_at (options, codec, SQUASH_LZG_OPT_LEVEL),
    squash_options_get_bool_at (options, codec, SQUASH_LZG_OPT_FAST),
    NULL,
    NULL
  };

#if UINT32_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(UINT32_MAX < uncompressed_size) ||
      HEDLEY_UNLIKELY(UINT32_MAX < *compressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  uint8_t* workmem = squash_calloc (LZG_WorkMemSize (&cfg), 1);
  if (HEDLEY_UNLIKELY(workmem == NULL))
    return squash_error (SQUASH_MEMORY);
  lzg_uint32_t res = LZG_EncodeFull ((const unsigned char*) uncompressed, (lzg_uint32_t) uncompressed_size,
                                     (unsigned char*) compressed, (lzg_uint32_t) *compressed_size,
                                     &cfg, workmem);
  squash_free (workmem);

  if (res == 0) {
    return squash_error (SQUASH_FAILED);
  } else {
#if SIZE_MAX < UINT32_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < res))
      return squash_error (SQUASH_RANGE);
#endif
    *compressed_size = (size_t) res;
    return SQUASH_OK;
  }
}
Beispiel #12
0
static SquashStatus
squash_bsc_decompress_buffer (SquashCodec* codec,
                              size_t* decompressed_size,
                              uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                              size_t compressed_size,
                              const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                              SquashOptions* options) {
#if INT_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(INT_MAX < compressed_size) ||
      HEDLEY_UNLIKELY(INT_MAX < *decompressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  const int features = squash_bsc_options_get_features (codec, options);

  int p_block_size, p_data_size;

  int res = bsc_block_info (compressed, (int) compressed_size, &p_block_size, &p_data_size, LIBBSC_DEFAULT_FEATURES);

  if (HEDLEY_UNLIKELY(p_block_size != (int) compressed_size))
    return squash_error (SQUASH_FAILED);
  if (HEDLEY_UNLIKELY(p_data_size > (int) *decompressed_size))
    return squash_error (SQUASH_BUFFER_FULL);

  res = bsc_decompress (compressed, p_block_size, decompressed, p_data_size, features);

  if (HEDLEY_UNLIKELY(res < 0))
    return squash_error (SQUASH_FAILED);

#if SIZE_MAX < INT_MAX
  if (HEDLEY_UNLIKELY(SIZE_MAX < p_data_size))
    return squash_error (SQUASH_RANGE);
#endif

  *decompressed_size = (size_t) p_data_size;

  return SQUASH_OK;
}
Beispiel #13
0
/**
 * @brief Read from a compressed file
 *
 * Attempt to read @a decompressed_size bytes of decompressed data
 * into the @a decompressed buffer.  The number of bytes of compressed
 * data read from the input file may be **significantly** more, or less,
 * than @a decompressed_size.
 *
 * The number of decompressed bytes successfully read from the file
 * will be stored in @a decompressed_read after this function is
 * execute.  This value will never be greater than @a
 * decompressed_size, but it may be less if there was an error or
 * the end of the input file was reached.
 *
 * @note Squash can, and frequently will, read more data from the
 * input file than necessary to produce the requested amount of
 * decompressed data.  There is no way to know how much input will be
 * required to produce the reuested output, or even how much input
 * *was* used.
 *
 * @param file the file to read from
 * @param decompressed_size number of bytes to attempt to write to @a decompressed
 * @param decompressed buffer to write the decompressed data to
 * @return the result of the operation
 * @retval SQUASH_OK successfully read some data
 * @retval SQUASH_END_OF_STREAM the end of the file was reached
 */
SquashStatus
squash_file_read (SquashFile* file,
                  size_t* decompressed_size,
                  uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)]) {
  assert (file != NULL);
  assert (decompressed_size != NULL);
  assert (decompressed != NULL);

  squash_file_lock (file);
  SquashStatus res = squash_file_read_unlocked (file, decompressed_size, decompressed);
  squash_file_unlock (file);

  return res;
}
Beispiel #14
0
static SquashStatus
squash_bsc_compress_buffer_unsafe (SquashCodec* codec,
                                   size_t* compressed_size,
                                   uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)],
                                   size_t uncompressed_size,
                                   const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                                   SquashOptions* options) {
  const int lzp_hash_size = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_LZP_HASH_SIZE);
  const int lzp_min_len = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_LZP_MIN_LEN);
  const int block_sorter = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_BLOCK_SORTER);
  const int coder = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_CODER);
  const int features = squash_bsc_options_get_features (codec, options);

#if INT_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(INT_MAX < uncompressed_size))
    return squash_error (SQUASH_RANGE);
#endif

  if (HEDLEY_UNLIKELY(*compressed_size < (uncompressed_size + LIBBSC_HEADER_SIZE)))
    return squash_error (SQUASH_BUFFER_FULL);

  const int res = bsc_compress (uncompressed, compressed, (int) uncompressed_size,
                                lzp_hash_size, lzp_min_len, block_sorter, coder, features);

  if (HEDLEY_UNLIKELY(res < 0)) {
    return squash_error (SQUASH_FAILED);
  }

#if SIZE_MAX < INT_MAX
  if (HEDLEY_UNLIKELY(SIZE_MAX < res))
    return squash_error (SQUASH_RANGE);
#endif

  *compressed_size = (size_t) res;

  return SQUASH_OK;
}
Beispiel #15
0
static size_t
squash_lzg_get_uncompressed_size (SquashCodec* codec,
                                  size_t compressed_size,
                                  const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)]) {
#if UINT32_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(UINT32_MAX < compressed_size))
    return (squash_error (SQUASH_RANGE), 0);
#endif

  const lzg_uint32_t res = LZG_DecodedSize ((const unsigned char*) compressed, (lzg_uint32_t) compressed_size);

#if SIZE_MAX < UINT32_MAX
  if (HEDLEY_UNLIKELY(SIZE_MAX < res))
    return (squash_error (SQUASH_RANGE), 0);
#endif

  return (size_t) res;
}
Beispiel #16
0
static size_t
squash_bsc_get_uncompressed_size (SquashCodec* codec,
                                  size_t compressed_size,
                                  const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)]) {
  int p_block_size, p_data_size;

#if INT_MAX < SIZE_MAX
  if (HEDLEY_UNLIKELY(INT_MAX < compressed_size))
    return (squash_error (SQUASH_RANGE), 0);
#endif

  int res = bsc_block_info (compressed, (int) compressed_size, &p_block_size, &p_data_size, LIBBSC_DEFAULT_FEATURES);

  if (res != LIBBSC_NO_ERROR) {
    return 0;
  } else {
#if SIZE_MAX < INT_MAX
    if (HEDLEY_UNLIKELY(SIZE_MAX < p_data_size))
      return (squash_error (SQUASH_RANGE), 0);
#endif
    return (size_t) p_data_size;
  }
}
Beispiel #17
0
/**
 * @brief Read from a compressed file
 *
 * This function is the same as @ref squash_file_read, except it will
 * not acquire a lock on the @ref SquashFile instance.  It should be
 * used only when there is no possibility of other threads accessing
 * the file, or if you have already acquired the lock with @ref
 * squash_file_lock.
 *
 * @param file the file to read from
 * @param decompressed_size number of bytes to attempt to write to @a decompressed
 * @param decompressed buffer to write the decompressed data to
 * @return the result of the operation
 * @retval SQUASH_OK successfully read some data
 * @retval SQUASH_END_OF_STREAM the end of the file was reached
 */
SquashStatus
squash_file_read_unlocked (SquashFile* file,
                           size_t* decompressed_size,
                           uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)]) {
  assert (file != NULL);
  assert (decompressed_size != NULL);
  assert (decompressed != NULL);

  if (HEDLEY_UNLIKELY(file->last_status < 0))
    return file->last_status;

  if (file->stream == NULL) {
    file->stream = squash_codec_create_stream_with_options (file->codec, SQUASH_STREAM_DECOMPRESS, file->options);
    if (HEDLEY_UNLIKELY(file->stream == NULL)) {
      return file->last_status = squash_error (SQUASH_FAILED);
    }
  }
  SquashStream* stream = file->stream;

  assert (stream->next_out == NULL);
  assert (stream->avail_out == 0);

  if (stream->state == SQUASH_STREAM_STATE_FINISHED) {
    *decompressed_size = 0;
    return SQUASH_END_OF_STREAM;
  }

  file->stream->next_out = decompressed;
  file->stream->avail_out = *decompressed_size;

  while (stream->avail_out != 0) {
    if (file->last_status < 0) {
      break;
    }

    if (stream->state == SQUASH_STREAM_STATE_FINISHED)
      break;

    if (file->last_status == SQUASH_PROCESSING) {
      if (stream->state < SQUASH_STREAM_STATE_FINISHING) {
        file->last_status = squash_stream_process (stream);
      } else {
        file->last_status = squash_stream_finish (stream);
      }

      continue;
    }

    assert (file->last_status == SQUASH_OK);

#if defined(SQUASH_MMAP_IO)
    if (file->map.data != MAP_FAILED)
      squash_mapped_file_destroy (&(file->map), true);

    if (squash_mapped_file_init_full(&(file->map), file->fp, SQUASH_FILE_BUF_SIZE, true, false)) {
      stream->next_in = file->map.data;
      stream->avail_in = file->map.size;
    } else
#endif
    {
      stream->next_in = file->buf;
      stream->avail_in = SQUASH_FREAD_UNLOCKED(file->buf, 1, SQUASH_FILE_BUF_SIZE, file->fp);
    }

    if (stream->avail_in == 0) {
      if (feof (file->fp)) {
        file->last_status = squash_stream_finish (stream);
      } else {
        file->last_status = squash_error (SQUASH_IO);
        break;
      }
    } else {
      file->last_status = squash_stream_process (stream);
    }
  }

  *decompressed_size = (stream->next_out - decompressed);

  stream->next_out = 0;
  stream->avail_out = 0;

  return file->last_status;
}
Beispiel #18
0
static SquashStatus
squash_file_write_internal (SquashFile* file,
                            size_t uncompressed_size,
                            const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                            SquashOperation operation) {
  SquashStatus res;

  assert (file != NULL);

  if (HEDLEY_UNLIKELY(file->last_status < 0))
    return file->last_status;

  if (file->stream == NULL) {
    file->stream = squash_codec_create_stream_with_options (file->codec, SQUASH_STREAM_COMPRESS, file->options);
    if (HEDLEY_UNLIKELY(file->stream == NULL)) {
      res = squash_error (SQUASH_FAILED);
      goto cleanup;
    }
  }

  assert (file->stream->next_in == NULL);
  assert (file->stream->avail_in == 0);
  assert (file->stream->next_out == NULL);
  assert (file->stream->avail_out == 0);

  file->stream->next_in = uncompressed;
  file->stream->avail_in = uncompressed_size;

  do {
    file->stream->next_out = file->buf;
    file->stream->avail_out = SQUASH_FILE_BUF_SIZE;

    switch (operation) {
      case SQUASH_OPERATION_PROCESS:
        res = squash_stream_process (file->stream);
        break;
      case SQUASH_OPERATION_FLUSH:
        res = squash_stream_flush (file->stream);
        break;
      case SQUASH_OPERATION_FINISH:
        res = squash_stream_finish (file->stream);
        break;
      case SQUASH_OPERATION_TERMINATE:
        HEDLEY_UNREACHABLE ();
        break;
    }

    if (res > 0 && file->stream->avail_out != SQUASH_FILE_BUF_SIZE) {
      size_t bytes_written = SQUASH_FWRITE_UNLOCKED(file->buf, 1, SQUASH_FILE_BUF_SIZE - file->stream->avail_out, file->fp);
      if (bytes_written != SQUASH_FILE_BUF_SIZE - file->stream->avail_out) {
        res = SQUASH_IO;
        goto cleanup;
      }
    }
  } while (res == SQUASH_PROCESSING);

 cleanup:

  if (file->stream != NULL) {
    file->stream->next_in = NULL;
    file->stream->avail_in = 0;
    file->stream->next_out = NULL;
    file->stream->avail_out = 0;
  }

  return file->last_status = res;
}
Beispiel #19
0
/**
 * @brief Write data to a compressed file without acquiring the lock
 *
 * This function is the same as @ref squash_file_write, except it will
 * not acquire a lock on the @ref SquashFile instance.  It should be
 * used only when there is no possibility of other threads accessing
 * the file, or if you have already acquired the lock with @ref
 * squash_file_lock.
 *
 * @param file file to write to
 * @param uncompressed_size number of bytes of uncompressed data in
 *   @a uncompressed to attempt to write
 * @param uncompressed data to write
 * @return result of the operation
 */
SquashStatus
squash_file_write_unlocked (SquashFile* file,
                            size_t uncompressed_size,
                            const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)]) {
  return squash_file_write_internal (file, uncompressed_size, uncompressed, SQUASH_OPERATION_PROCESS);
}