181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 281ad8388SMartin Matuska // 381ad8388SMartin Matuska /// \file common.h 481ad8388SMartin Matuska /// \brief Common functions needed in many places in liblzma 581ad8388SMartin Matuska // 681ad8388SMartin Matuska // Author: Lasse Collin 781ad8388SMartin Matuska // 881ad8388SMartin Matuska // This file has been put into the public domain. 981ad8388SMartin Matuska // You can do whatever you want with this file. 1081ad8388SMartin Matuska // 1181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 1281ad8388SMartin Matuska 1381ad8388SMartin Matuska #include "common.h" 1481ad8388SMartin Matuska 1581ad8388SMartin Matuska 1681ad8388SMartin Matuska ///////////// 1781ad8388SMartin Matuska // Version // 1881ad8388SMartin Matuska ///////////// 1981ad8388SMartin Matuska 2081ad8388SMartin Matuska extern LZMA_API(uint32_t) 2181ad8388SMartin Matuska lzma_version_number(void) 2281ad8388SMartin Matuska { 2381ad8388SMartin Matuska return LZMA_VERSION; 2481ad8388SMartin Matuska } 2581ad8388SMartin Matuska 2681ad8388SMartin Matuska 2781ad8388SMartin Matuska extern LZMA_API(const char *) 2881ad8388SMartin Matuska lzma_version_string(void) 2981ad8388SMartin Matuska { 3081ad8388SMartin Matuska return LZMA_VERSION_STRING; 3181ad8388SMartin Matuska } 3281ad8388SMartin Matuska 3381ad8388SMartin Matuska 3481ad8388SMartin Matuska /////////////////////// 3581ad8388SMartin Matuska // Memory allocation // 3681ad8388SMartin Matuska /////////////////////// 3781ad8388SMartin Matuska 3881ad8388SMartin Matuska extern void * lzma_attribute((malloc)) 3981ad8388SMartin Matuska lzma_alloc(size_t size, lzma_allocator *allocator) 4081ad8388SMartin Matuska { 4181ad8388SMartin Matuska // Some malloc() variants return NULL if called with size == 0. 4281ad8388SMartin Matuska if (size == 0) 4381ad8388SMartin Matuska size = 1; 4481ad8388SMartin Matuska 4581ad8388SMartin Matuska void *ptr; 4681ad8388SMartin Matuska 4781ad8388SMartin Matuska if (allocator != NULL && allocator->alloc != NULL) 4881ad8388SMartin Matuska ptr = allocator->alloc(allocator->opaque, 1, size); 4981ad8388SMartin Matuska else 5081ad8388SMartin Matuska ptr = malloc(size); 5181ad8388SMartin Matuska 5281ad8388SMartin Matuska return ptr; 5381ad8388SMartin Matuska } 5481ad8388SMartin Matuska 5581ad8388SMartin Matuska 5681ad8388SMartin Matuska extern void 5781ad8388SMartin Matuska lzma_free(void *ptr, lzma_allocator *allocator) 5881ad8388SMartin Matuska { 5981ad8388SMartin Matuska if (allocator != NULL && allocator->free != NULL) 6081ad8388SMartin Matuska allocator->free(allocator->opaque, ptr); 6181ad8388SMartin Matuska else 6281ad8388SMartin Matuska free(ptr); 6381ad8388SMartin Matuska 6481ad8388SMartin Matuska return; 6581ad8388SMartin Matuska } 6681ad8388SMartin Matuska 6781ad8388SMartin Matuska 6881ad8388SMartin Matuska ////////// 6981ad8388SMartin Matuska // Misc // 7081ad8388SMartin Matuska ////////// 7181ad8388SMartin Matuska 7281ad8388SMartin Matuska extern size_t 7381ad8388SMartin Matuska lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, 7481ad8388SMartin Matuska size_t in_size, uint8_t *restrict out, 7581ad8388SMartin Matuska size_t *restrict out_pos, size_t out_size) 7681ad8388SMartin Matuska { 7781ad8388SMartin Matuska const size_t in_avail = in_size - *in_pos; 7881ad8388SMartin Matuska const size_t out_avail = out_size - *out_pos; 79e0f0e66dSMartin Matuska const size_t copy_size = my_min(in_avail, out_avail); 8081ad8388SMartin Matuska 8181ad8388SMartin Matuska memcpy(out + *out_pos, in + *in_pos, copy_size); 8281ad8388SMartin Matuska 8381ad8388SMartin Matuska *in_pos += copy_size; 8481ad8388SMartin Matuska *out_pos += copy_size; 8581ad8388SMartin Matuska 8681ad8388SMartin Matuska return copy_size; 8781ad8388SMartin Matuska } 8881ad8388SMartin Matuska 8981ad8388SMartin Matuska 9081ad8388SMartin Matuska extern lzma_ret 9181ad8388SMartin Matuska lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator, 9281ad8388SMartin Matuska const lzma_filter_info *filters) 9381ad8388SMartin Matuska { 9481ad8388SMartin Matuska lzma_next_coder_init(filters[0].init, next, allocator); 9581ad8388SMartin Matuska next->id = filters[0].id; 9681ad8388SMartin Matuska return filters[0].init == NULL 9781ad8388SMartin Matuska ? LZMA_OK : filters[0].init(next, allocator, filters); 9881ad8388SMartin Matuska } 9981ad8388SMartin Matuska 10081ad8388SMartin Matuska 10181ad8388SMartin Matuska extern lzma_ret 10281ad8388SMartin Matuska lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator, 10381ad8388SMartin Matuska const lzma_filter *reversed_filters) 10481ad8388SMartin Matuska { 10581ad8388SMartin Matuska // Check that the application isn't trying to change the Filter ID. 10681ad8388SMartin Matuska // End of filters is indicated with LZMA_VLI_UNKNOWN in both 10781ad8388SMartin Matuska // reversed_filters[0].id and next->id. 10881ad8388SMartin Matuska if (reversed_filters[0].id != next->id) 10981ad8388SMartin Matuska return LZMA_PROG_ERROR; 11081ad8388SMartin Matuska 11181ad8388SMartin Matuska if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) 11281ad8388SMartin Matuska return LZMA_OK; 11381ad8388SMartin Matuska 11481ad8388SMartin Matuska assert(next->update != NULL); 11581ad8388SMartin Matuska return next->update(next->coder, allocator, NULL, reversed_filters); 11681ad8388SMartin Matuska } 11781ad8388SMartin Matuska 11881ad8388SMartin Matuska 11981ad8388SMartin Matuska extern void 12081ad8388SMartin Matuska lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator) 12181ad8388SMartin Matuska { 12281ad8388SMartin Matuska if (next->init != (uintptr_t)(NULL)) { 12381ad8388SMartin Matuska // To avoid tiny end functions that simply call 12481ad8388SMartin Matuska // lzma_free(coder, allocator), we allow leaving next->end 12581ad8388SMartin Matuska // NULL and call lzma_free() here. 12681ad8388SMartin Matuska if (next->end != NULL) 12781ad8388SMartin Matuska next->end(next->coder, allocator); 12881ad8388SMartin Matuska else 12981ad8388SMartin Matuska lzma_free(next->coder, allocator); 13081ad8388SMartin Matuska 13181ad8388SMartin Matuska // Reset the variables so the we don't accidentally think 13281ad8388SMartin Matuska // that it is an already initialized coder. 13381ad8388SMartin Matuska *next = LZMA_NEXT_CODER_INIT; 13481ad8388SMartin Matuska } 13581ad8388SMartin Matuska 13681ad8388SMartin Matuska return; 13781ad8388SMartin Matuska } 13881ad8388SMartin Matuska 13981ad8388SMartin Matuska 14081ad8388SMartin Matuska ////////////////////////////////////// 14181ad8388SMartin Matuska // External to internal API wrapper // 14281ad8388SMartin Matuska ////////////////////////////////////// 14381ad8388SMartin Matuska 14481ad8388SMartin Matuska extern lzma_ret 14581ad8388SMartin Matuska lzma_strm_init(lzma_stream *strm) 14681ad8388SMartin Matuska { 14781ad8388SMartin Matuska if (strm == NULL) 14881ad8388SMartin Matuska return LZMA_PROG_ERROR; 14981ad8388SMartin Matuska 15081ad8388SMartin Matuska if (strm->internal == NULL) { 15181ad8388SMartin Matuska strm->internal = lzma_alloc(sizeof(lzma_internal), 15281ad8388SMartin Matuska strm->allocator); 15381ad8388SMartin Matuska if (strm->internal == NULL) 15481ad8388SMartin Matuska return LZMA_MEM_ERROR; 15581ad8388SMartin Matuska 15681ad8388SMartin Matuska strm->internal->next = LZMA_NEXT_CODER_INIT; 15781ad8388SMartin Matuska } 15881ad8388SMartin Matuska 15981ad8388SMartin Matuska strm->internal->supported_actions[LZMA_RUN] = false; 16081ad8388SMartin Matuska strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false; 16181ad8388SMartin Matuska strm->internal->supported_actions[LZMA_FULL_FLUSH] = false; 16281ad8388SMartin Matuska strm->internal->supported_actions[LZMA_FINISH] = false; 16381ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 16481ad8388SMartin Matuska strm->internal->allow_buf_error = false; 16581ad8388SMartin Matuska 16681ad8388SMartin Matuska strm->total_in = 0; 16781ad8388SMartin Matuska strm->total_out = 0; 16881ad8388SMartin Matuska 16981ad8388SMartin Matuska return LZMA_OK; 17081ad8388SMartin Matuska } 17181ad8388SMartin Matuska 17281ad8388SMartin Matuska 17381ad8388SMartin Matuska extern LZMA_API(lzma_ret) 17481ad8388SMartin Matuska lzma_code(lzma_stream *strm, lzma_action action) 17581ad8388SMartin Matuska { 17681ad8388SMartin Matuska // Sanity checks 17781ad8388SMartin Matuska if ((strm->next_in == NULL && strm->avail_in != 0) 17881ad8388SMartin Matuska || (strm->next_out == NULL && strm->avail_out != 0) 17981ad8388SMartin Matuska || strm->internal == NULL 18081ad8388SMartin Matuska || strm->internal->next.code == NULL 18181ad8388SMartin Matuska || (unsigned int)(action) > LZMA_FINISH 18281ad8388SMartin Matuska || !strm->internal->supported_actions[action]) 18381ad8388SMartin Matuska return LZMA_PROG_ERROR; 18481ad8388SMartin Matuska 185*542aef48SMartin Matuska // Check if unsupported members have been set to non-zero or non-NULL, 186*542aef48SMartin Matuska // which would indicate that some new feature is wanted. 187*542aef48SMartin Matuska if (strm->reserved_ptr1 != NULL 188*542aef48SMartin Matuska || strm->reserved_ptr2 != NULL 189*542aef48SMartin Matuska || strm->reserved_ptr3 != NULL 190*542aef48SMartin Matuska || strm->reserved_ptr4 != NULL 191*542aef48SMartin Matuska || strm->reserved_int1 != 0 192*542aef48SMartin Matuska || strm->reserved_int2 != 0 193*542aef48SMartin Matuska || strm->reserved_int3 != 0 194*542aef48SMartin Matuska || strm->reserved_int4 != 0 195*542aef48SMartin Matuska || strm->reserved_enum1 != LZMA_RESERVED_ENUM 196*542aef48SMartin Matuska || strm->reserved_enum2 != LZMA_RESERVED_ENUM) 197*542aef48SMartin Matuska return LZMA_OPTIONS_ERROR; 198*542aef48SMartin Matuska 19981ad8388SMartin Matuska switch (strm->internal->sequence) { 20081ad8388SMartin Matuska case ISEQ_RUN: 20181ad8388SMartin Matuska switch (action) { 20281ad8388SMartin Matuska case LZMA_RUN: 20381ad8388SMartin Matuska break; 20481ad8388SMartin Matuska 20581ad8388SMartin Matuska case LZMA_SYNC_FLUSH: 20681ad8388SMartin Matuska strm->internal->sequence = ISEQ_SYNC_FLUSH; 20781ad8388SMartin Matuska break; 20881ad8388SMartin Matuska 20981ad8388SMartin Matuska case LZMA_FULL_FLUSH: 21081ad8388SMartin Matuska strm->internal->sequence = ISEQ_FULL_FLUSH; 21181ad8388SMartin Matuska break; 21281ad8388SMartin Matuska 21381ad8388SMartin Matuska case LZMA_FINISH: 21481ad8388SMartin Matuska strm->internal->sequence = ISEQ_FINISH; 21581ad8388SMartin Matuska break; 21681ad8388SMartin Matuska } 21781ad8388SMartin Matuska 21881ad8388SMartin Matuska break; 21981ad8388SMartin Matuska 22081ad8388SMartin Matuska case ISEQ_SYNC_FLUSH: 22181ad8388SMartin Matuska // The same action must be used until we return 22281ad8388SMartin Matuska // LZMA_STREAM_END, and the amount of input must not change. 22381ad8388SMartin Matuska if (action != LZMA_SYNC_FLUSH 22481ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 22581ad8388SMartin Matuska return LZMA_PROG_ERROR; 22681ad8388SMartin Matuska 22781ad8388SMartin Matuska break; 22881ad8388SMartin Matuska 22981ad8388SMartin Matuska case ISEQ_FULL_FLUSH: 23081ad8388SMartin Matuska if (action != LZMA_FULL_FLUSH 23181ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 23281ad8388SMartin Matuska return LZMA_PROG_ERROR; 23381ad8388SMartin Matuska 23481ad8388SMartin Matuska break; 23581ad8388SMartin Matuska 23681ad8388SMartin Matuska case ISEQ_FINISH: 23781ad8388SMartin Matuska if (action != LZMA_FINISH 23881ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 23981ad8388SMartin Matuska return LZMA_PROG_ERROR; 24081ad8388SMartin Matuska 24181ad8388SMartin Matuska break; 24281ad8388SMartin Matuska 24381ad8388SMartin Matuska case ISEQ_END: 24481ad8388SMartin Matuska return LZMA_STREAM_END; 24581ad8388SMartin Matuska 24681ad8388SMartin Matuska case ISEQ_ERROR: 24781ad8388SMartin Matuska default: 24881ad8388SMartin Matuska return LZMA_PROG_ERROR; 24981ad8388SMartin Matuska } 25081ad8388SMartin Matuska 25181ad8388SMartin Matuska size_t in_pos = 0; 25281ad8388SMartin Matuska size_t out_pos = 0; 25381ad8388SMartin Matuska lzma_ret ret = strm->internal->next.code( 25481ad8388SMartin Matuska strm->internal->next.coder, strm->allocator, 25581ad8388SMartin Matuska strm->next_in, &in_pos, strm->avail_in, 25681ad8388SMartin Matuska strm->next_out, &out_pos, strm->avail_out, action); 25781ad8388SMartin Matuska 25881ad8388SMartin Matuska strm->next_in += in_pos; 25981ad8388SMartin Matuska strm->avail_in -= in_pos; 26081ad8388SMartin Matuska strm->total_in += in_pos; 26181ad8388SMartin Matuska 26281ad8388SMartin Matuska strm->next_out += out_pos; 26381ad8388SMartin Matuska strm->avail_out -= out_pos; 26481ad8388SMartin Matuska strm->total_out += out_pos; 26581ad8388SMartin Matuska 26681ad8388SMartin Matuska strm->internal->avail_in = strm->avail_in; 26781ad8388SMartin Matuska 26881ad8388SMartin Matuska switch (ret) { 26981ad8388SMartin Matuska case LZMA_OK: 27081ad8388SMartin Matuska // Don't return LZMA_BUF_ERROR when it happens the first time. 27181ad8388SMartin Matuska // This is to avoid returning LZMA_BUF_ERROR when avail_out 27281ad8388SMartin Matuska // was zero but still there was no more data left to written 27381ad8388SMartin Matuska // to next_out. 27481ad8388SMartin Matuska if (out_pos == 0 && in_pos == 0) { 27581ad8388SMartin Matuska if (strm->internal->allow_buf_error) 27681ad8388SMartin Matuska ret = LZMA_BUF_ERROR; 27781ad8388SMartin Matuska else 27881ad8388SMartin Matuska strm->internal->allow_buf_error = true; 27981ad8388SMartin Matuska } else { 28081ad8388SMartin Matuska strm->internal->allow_buf_error = false; 28181ad8388SMartin Matuska } 28281ad8388SMartin Matuska break; 28381ad8388SMartin Matuska 28481ad8388SMartin Matuska case LZMA_STREAM_END: 28581ad8388SMartin Matuska if (strm->internal->sequence == ISEQ_SYNC_FLUSH 28681ad8388SMartin Matuska || strm->internal->sequence == ISEQ_FULL_FLUSH) 28781ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 28881ad8388SMartin Matuska else 28981ad8388SMartin Matuska strm->internal->sequence = ISEQ_END; 29081ad8388SMartin Matuska 29181ad8388SMartin Matuska // Fall through 29281ad8388SMartin Matuska 29381ad8388SMartin Matuska case LZMA_NO_CHECK: 29481ad8388SMartin Matuska case LZMA_UNSUPPORTED_CHECK: 29581ad8388SMartin Matuska case LZMA_GET_CHECK: 29681ad8388SMartin Matuska case LZMA_MEMLIMIT_ERROR: 29781ad8388SMartin Matuska // Something else than LZMA_OK, but not a fatal error, 29881ad8388SMartin Matuska // that is, coding may be continued (except if ISEQ_END). 29981ad8388SMartin Matuska strm->internal->allow_buf_error = false; 30081ad8388SMartin Matuska break; 30181ad8388SMartin Matuska 30281ad8388SMartin Matuska default: 30381ad8388SMartin Matuska // All the other errors are fatal; coding cannot be continued. 30481ad8388SMartin Matuska assert(ret != LZMA_BUF_ERROR); 30581ad8388SMartin Matuska strm->internal->sequence = ISEQ_ERROR; 30681ad8388SMartin Matuska break; 30781ad8388SMartin Matuska } 30881ad8388SMartin Matuska 30981ad8388SMartin Matuska return ret; 31081ad8388SMartin Matuska } 31181ad8388SMartin Matuska 31281ad8388SMartin Matuska 31381ad8388SMartin Matuska extern LZMA_API(void) 31481ad8388SMartin Matuska lzma_end(lzma_stream *strm) 31581ad8388SMartin Matuska { 31681ad8388SMartin Matuska if (strm != NULL && strm->internal != NULL) { 31781ad8388SMartin Matuska lzma_next_end(&strm->internal->next, strm->allocator); 31881ad8388SMartin Matuska lzma_free(strm->internal, strm->allocator); 31981ad8388SMartin Matuska strm->internal = NULL; 32081ad8388SMartin Matuska } 32181ad8388SMartin Matuska 32281ad8388SMartin Matuska return; 32381ad8388SMartin Matuska } 32481ad8388SMartin Matuska 32581ad8388SMartin Matuska 32681ad8388SMartin Matuska extern LZMA_API(lzma_check) 32781ad8388SMartin Matuska lzma_get_check(const lzma_stream *strm) 32881ad8388SMartin Matuska { 32981ad8388SMartin Matuska // Return LZMA_CHECK_NONE if we cannot know the check type. 33081ad8388SMartin Matuska // It's a bug in the application if this happens. 33181ad8388SMartin Matuska if (strm->internal->next.get_check == NULL) 33281ad8388SMartin Matuska return LZMA_CHECK_NONE; 33381ad8388SMartin Matuska 33481ad8388SMartin Matuska return strm->internal->next.get_check(strm->internal->next.coder); 33581ad8388SMartin Matuska } 33681ad8388SMartin Matuska 33781ad8388SMartin Matuska 33881ad8388SMartin Matuska extern LZMA_API(uint64_t) 33981ad8388SMartin Matuska lzma_memusage(const lzma_stream *strm) 34081ad8388SMartin Matuska { 34181ad8388SMartin Matuska uint64_t memusage; 34281ad8388SMartin Matuska uint64_t old_memlimit; 34381ad8388SMartin Matuska 34481ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 34581ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 34681ad8388SMartin Matuska || strm->internal->next.memconfig( 34781ad8388SMartin Matuska strm->internal->next.coder, 34881ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 34981ad8388SMartin Matuska return 0; 35081ad8388SMartin Matuska 35181ad8388SMartin Matuska return memusage; 35281ad8388SMartin Matuska } 35381ad8388SMartin Matuska 35481ad8388SMartin Matuska 35581ad8388SMartin Matuska extern LZMA_API(uint64_t) 35681ad8388SMartin Matuska lzma_memlimit_get(const lzma_stream *strm) 35781ad8388SMartin Matuska { 35881ad8388SMartin Matuska uint64_t old_memlimit; 35981ad8388SMartin Matuska uint64_t memusage; 36081ad8388SMartin Matuska 36181ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 36281ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 36381ad8388SMartin Matuska || strm->internal->next.memconfig( 36481ad8388SMartin Matuska strm->internal->next.coder, 36581ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 36681ad8388SMartin Matuska return 0; 36781ad8388SMartin Matuska 36881ad8388SMartin Matuska return old_memlimit; 36981ad8388SMartin Matuska } 37081ad8388SMartin Matuska 37181ad8388SMartin Matuska 37281ad8388SMartin Matuska extern LZMA_API(lzma_ret) 37381ad8388SMartin Matuska lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) 37481ad8388SMartin Matuska { 37581ad8388SMartin Matuska // Dummy variables to simplify memconfig functions 37681ad8388SMartin Matuska uint64_t old_memlimit; 37781ad8388SMartin Matuska uint64_t memusage; 37881ad8388SMartin Matuska 37981ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 38081ad8388SMartin Matuska || strm->internal->next.memconfig == NULL) 38181ad8388SMartin Matuska return LZMA_PROG_ERROR; 38281ad8388SMartin Matuska 38381ad8388SMartin Matuska if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE) 38481ad8388SMartin Matuska return LZMA_MEMLIMIT_ERROR; 38581ad8388SMartin Matuska 38681ad8388SMartin Matuska return strm->internal->next.memconfig(strm->internal->next.coder, 38781ad8388SMartin Matuska &memusage, &old_memlimit, new_memlimit); 38881ad8388SMartin Matuska } 389