/** * @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; }
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); }