Ejemplo n.º 1
0
Archivo: file.c Proyecto: jibsen/squash
/**
 * @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[SQUASH_ARRAY_PARAM(*decompressed_size)]) {
  assert (file != NULL);
  assert (decompressed_size != NULL);
  assert (decompressed != NULL);

  if (SQUASH_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 (SQUASH_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;
}
Ejemplo n.º 2
0
bool
squash_mapped_file_init (SquashMappedFile* mapped, FILE* fp, size_t size, bool writable) {
  return squash_mapped_file_init_full (mapped, fp, size, false, writable);
}