181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 281ad8388SMartin Matuska // 3a8675d92SXin LI /// \file common.c 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 38*ca6a6373SXin LI lzma_attr_alloc_size(1) 39*ca6a6373SXin LI extern void * 4053200025SRui Paulo lzma_alloc(size_t size, const lzma_allocator *allocator) 4181ad8388SMartin Matuska { 4281ad8388SMartin Matuska // Some malloc() variants return NULL if called with size == 0. 4381ad8388SMartin Matuska if (size == 0) 4481ad8388SMartin Matuska size = 1; 4581ad8388SMartin Matuska 4681ad8388SMartin Matuska void *ptr; 4781ad8388SMartin Matuska 4881ad8388SMartin Matuska if (allocator != NULL && allocator->alloc != NULL) 4981ad8388SMartin Matuska ptr = allocator->alloc(allocator->opaque, 1, size); 5081ad8388SMartin Matuska else 5181ad8388SMartin Matuska ptr = malloc(size); 5281ad8388SMartin Matuska 5381ad8388SMartin Matuska return ptr; 5481ad8388SMartin Matuska } 5581ad8388SMartin Matuska 5681ad8388SMartin Matuska 57*ca6a6373SXin LI lzma_attr_alloc_size(1) 58*ca6a6373SXin LI extern void * 5953200025SRui Paulo lzma_alloc_zero(size_t size, const lzma_allocator *allocator) 6053200025SRui Paulo { 6153200025SRui Paulo // Some calloc() variants return NULL if called with size == 0. 6253200025SRui Paulo if (size == 0) 6353200025SRui Paulo size = 1; 6453200025SRui Paulo 6553200025SRui Paulo void *ptr; 6653200025SRui Paulo 6753200025SRui Paulo if (allocator != NULL && allocator->alloc != NULL) { 6853200025SRui Paulo ptr = allocator->alloc(allocator->opaque, 1, size); 6953200025SRui Paulo if (ptr != NULL) 7053200025SRui Paulo memzero(ptr, size); 7153200025SRui Paulo } else { 7253200025SRui Paulo ptr = calloc(1, size); 7353200025SRui Paulo } 7453200025SRui Paulo 7553200025SRui Paulo return ptr; 7653200025SRui Paulo } 7753200025SRui Paulo 7853200025SRui Paulo 7981ad8388SMartin Matuska extern void 8053200025SRui Paulo lzma_free(void *ptr, const lzma_allocator *allocator) 8181ad8388SMartin Matuska { 8281ad8388SMartin Matuska if (allocator != NULL && allocator->free != NULL) 8381ad8388SMartin Matuska allocator->free(allocator->opaque, ptr); 8481ad8388SMartin Matuska else 8581ad8388SMartin Matuska free(ptr); 8681ad8388SMartin Matuska 8781ad8388SMartin Matuska return; 8881ad8388SMartin Matuska } 8981ad8388SMartin Matuska 9081ad8388SMartin Matuska 9181ad8388SMartin Matuska ////////// 9281ad8388SMartin Matuska // Misc // 9381ad8388SMartin Matuska ////////// 9481ad8388SMartin Matuska 9581ad8388SMartin Matuska extern size_t 9681ad8388SMartin Matuska lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, 9781ad8388SMartin Matuska size_t in_size, uint8_t *restrict out, 9881ad8388SMartin Matuska size_t *restrict out_pos, size_t out_size) 9981ad8388SMartin Matuska { 10081ad8388SMartin Matuska const size_t in_avail = in_size - *in_pos; 10181ad8388SMartin Matuska const size_t out_avail = out_size - *out_pos; 102e0f0e66dSMartin Matuska const size_t copy_size = my_min(in_avail, out_avail); 10381ad8388SMartin Matuska 104a8675d92SXin LI // Call memcpy() only if there is something to copy. If there is 105a8675d92SXin LI // nothing to copy, in or out might be NULL and then the memcpy() 106a8675d92SXin LI // call would trigger undefined behavior. 107a8675d92SXin LI if (copy_size > 0) 10881ad8388SMartin Matuska memcpy(out + *out_pos, in + *in_pos, copy_size); 10981ad8388SMartin Matuska 11081ad8388SMartin Matuska *in_pos += copy_size; 11181ad8388SMartin Matuska *out_pos += copy_size; 11281ad8388SMartin Matuska 11381ad8388SMartin Matuska return copy_size; 11481ad8388SMartin Matuska } 11581ad8388SMartin Matuska 11681ad8388SMartin Matuska 11781ad8388SMartin Matuska extern lzma_ret 11853200025SRui Paulo lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, 11981ad8388SMartin Matuska const lzma_filter_info *filters) 12081ad8388SMartin Matuska { 12181ad8388SMartin Matuska lzma_next_coder_init(filters[0].init, next, allocator); 12281ad8388SMartin Matuska next->id = filters[0].id; 12381ad8388SMartin Matuska return filters[0].init == NULL 12481ad8388SMartin Matuska ? LZMA_OK : filters[0].init(next, allocator, filters); 12581ad8388SMartin Matuska } 12681ad8388SMartin Matuska 12781ad8388SMartin Matuska 12881ad8388SMartin Matuska extern lzma_ret 12953200025SRui Paulo lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator, 13081ad8388SMartin Matuska const lzma_filter *reversed_filters) 13181ad8388SMartin Matuska { 13281ad8388SMartin Matuska // Check that the application isn't trying to change the Filter ID. 13381ad8388SMartin Matuska // End of filters is indicated with LZMA_VLI_UNKNOWN in both 13481ad8388SMartin Matuska // reversed_filters[0].id and next->id. 13581ad8388SMartin Matuska if (reversed_filters[0].id != next->id) 13681ad8388SMartin Matuska return LZMA_PROG_ERROR; 13781ad8388SMartin Matuska 13881ad8388SMartin Matuska if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) 13981ad8388SMartin Matuska return LZMA_OK; 14081ad8388SMartin Matuska 14181ad8388SMartin Matuska assert(next->update != NULL); 14281ad8388SMartin Matuska return next->update(next->coder, allocator, NULL, reversed_filters); 14381ad8388SMartin Matuska } 14481ad8388SMartin Matuska 14581ad8388SMartin Matuska 14681ad8388SMartin Matuska extern void 14753200025SRui Paulo lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator) 14881ad8388SMartin Matuska { 14981ad8388SMartin Matuska if (next->init != (uintptr_t)(NULL)) { 15081ad8388SMartin Matuska // To avoid tiny end functions that simply call 15181ad8388SMartin Matuska // lzma_free(coder, allocator), we allow leaving next->end 15281ad8388SMartin Matuska // NULL and call lzma_free() here. 15381ad8388SMartin Matuska if (next->end != NULL) 15481ad8388SMartin Matuska next->end(next->coder, allocator); 15581ad8388SMartin Matuska else 15681ad8388SMartin Matuska lzma_free(next->coder, allocator); 15781ad8388SMartin Matuska 15881ad8388SMartin Matuska // Reset the variables so the we don't accidentally think 15981ad8388SMartin Matuska // that it is an already initialized coder. 16081ad8388SMartin Matuska *next = LZMA_NEXT_CODER_INIT; 16181ad8388SMartin Matuska } 16281ad8388SMartin Matuska 16381ad8388SMartin Matuska return; 16481ad8388SMartin Matuska } 16581ad8388SMartin Matuska 16681ad8388SMartin Matuska 16781ad8388SMartin Matuska ////////////////////////////////////// 16881ad8388SMartin Matuska // External to internal API wrapper // 16981ad8388SMartin Matuska ////////////////////////////////////// 17081ad8388SMartin Matuska 17181ad8388SMartin Matuska extern lzma_ret 17281ad8388SMartin Matuska lzma_strm_init(lzma_stream *strm) 17381ad8388SMartin Matuska { 17481ad8388SMartin Matuska if (strm == NULL) 17581ad8388SMartin Matuska return LZMA_PROG_ERROR; 17681ad8388SMartin Matuska 17781ad8388SMartin Matuska if (strm->internal == NULL) { 17881ad8388SMartin Matuska strm->internal = lzma_alloc(sizeof(lzma_internal), 17981ad8388SMartin Matuska strm->allocator); 18081ad8388SMartin Matuska if (strm->internal == NULL) 18181ad8388SMartin Matuska return LZMA_MEM_ERROR; 18281ad8388SMartin Matuska 18381ad8388SMartin Matuska strm->internal->next = LZMA_NEXT_CODER_INIT; 18481ad8388SMartin Matuska } 18581ad8388SMartin Matuska 18653200025SRui Paulo memzero(strm->internal->supported_actions, 18753200025SRui Paulo sizeof(strm->internal->supported_actions)); 18881ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 18981ad8388SMartin Matuska strm->internal->allow_buf_error = false; 19081ad8388SMartin Matuska 19181ad8388SMartin Matuska strm->total_in = 0; 19281ad8388SMartin Matuska strm->total_out = 0; 19381ad8388SMartin Matuska 19481ad8388SMartin Matuska return LZMA_OK; 19581ad8388SMartin Matuska } 19681ad8388SMartin Matuska 19781ad8388SMartin Matuska 19881ad8388SMartin Matuska extern LZMA_API(lzma_ret) 19981ad8388SMartin Matuska lzma_code(lzma_stream *strm, lzma_action action) 20081ad8388SMartin Matuska { 20181ad8388SMartin Matuska // Sanity checks 20281ad8388SMartin Matuska if ((strm->next_in == NULL && strm->avail_in != 0) 20381ad8388SMartin Matuska || (strm->next_out == NULL && strm->avail_out != 0) 20481ad8388SMartin Matuska || strm->internal == NULL 20581ad8388SMartin Matuska || strm->internal->next.code == NULL 20653200025SRui Paulo || (unsigned int)(action) > LZMA_ACTION_MAX 20781ad8388SMartin Matuska || !strm->internal->supported_actions[action]) 20881ad8388SMartin Matuska return LZMA_PROG_ERROR; 20981ad8388SMartin Matuska 210542aef48SMartin Matuska // Check if unsupported members have been set to non-zero or non-NULL, 211542aef48SMartin Matuska // which would indicate that some new feature is wanted. 212542aef48SMartin Matuska if (strm->reserved_ptr1 != NULL 213542aef48SMartin Matuska || strm->reserved_ptr2 != NULL 214542aef48SMartin Matuska || strm->reserved_ptr3 != NULL 215542aef48SMartin Matuska || strm->reserved_ptr4 != NULL 216542aef48SMartin Matuska || strm->reserved_int2 != 0 217542aef48SMartin Matuska || strm->reserved_int3 != 0 218542aef48SMartin Matuska || strm->reserved_int4 != 0 219542aef48SMartin Matuska || strm->reserved_enum1 != LZMA_RESERVED_ENUM 220542aef48SMartin Matuska || strm->reserved_enum2 != LZMA_RESERVED_ENUM) 221542aef48SMartin Matuska return LZMA_OPTIONS_ERROR; 222542aef48SMartin Matuska 22381ad8388SMartin Matuska switch (strm->internal->sequence) { 22481ad8388SMartin Matuska case ISEQ_RUN: 22581ad8388SMartin Matuska switch (action) { 22681ad8388SMartin Matuska case LZMA_RUN: 22781ad8388SMartin Matuska break; 22881ad8388SMartin Matuska 22981ad8388SMartin Matuska case LZMA_SYNC_FLUSH: 23081ad8388SMartin Matuska strm->internal->sequence = ISEQ_SYNC_FLUSH; 23181ad8388SMartin Matuska break; 23281ad8388SMartin Matuska 23381ad8388SMartin Matuska case LZMA_FULL_FLUSH: 23481ad8388SMartin Matuska strm->internal->sequence = ISEQ_FULL_FLUSH; 23581ad8388SMartin Matuska break; 23681ad8388SMartin Matuska 23781ad8388SMartin Matuska case LZMA_FINISH: 23881ad8388SMartin Matuska strm->internal->sequence = ISEQ_FINISH; 23981ad8388SMartin Matuska break; 24053200025SRui Paulo 24153200025SRui Paulo case LZMA_FULL_BARRIER: 24253200025SRui Paulo strm->internal->sequence = ISEQ_FULL_BARRIER; 24353200025SRui Paulo break; 24481ad8388SMartin Matuska } 24581ad8388SMartin Matuska 24681ad8388SMartin Matuska break; 24781ad8388SMartin Matuska 24881ad8388SMartin Matuska case ISEQ_SYNC_FLUSH: 24981ad8388SMartin Matuska // The same action must be used until we return 25081ad8388SMartin Matuska // LZMA_STREAM_END, and the amount of input must not change. 25181ad8388SMartin Matuska if (action != LZMA_SYNC_FLUSH 25281ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 25381ad8388SMartin Matuska return LZMA_PROG_ERROR; 25481ad8388SMartin Matuska 25581ad8388SMartin Matuska break; 25681ad8388SMartin Matuska 25781ad8388SMartin Matuska case ISEQ_FULL_FLUSH: 25881ad8388SMartin Matuska if (action != LZMA_FULL_FLUSH 25981ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 26081ad8388SMartin Matuska return LZMA_PROG_ERROR; 26181ad8388SMartin Matuska 26281ad8388SMartin Matuska break; 26381ad8388SMartin Matuska 26481ad8388SMartin Matuska case ISEQ_FINISH: 26581ad8388SMartin Matuska if (action != LZMA_FINISH 26681ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 26781ad8388SMartin Matuska return LZMA_PROG_ERROR; 26881ad8388SMartin Matuska 26981ad8388SMartin Matuska break; 27081ad8388SMartin Matuska 27153200025SRui Paulo case ISEQ_FULL_BARRIER: 27253200025SRui Paulo if (action != LZMA_FULL_BARRIER 27353200025SRui Paulo || strm->internal->avail_in != strm->avail_in) 27453200025SRui Paulo return LZMA_PROG_ERROR; 27553200025SRui Paulo 27653200025SRui Paulo break; 27753200025SRui Paulo 27881ad8388SMartin Matuska case ISEQ_END: 27981ad8388SMartin Matuska return LZMA_STREAM_END; 28081ad8388SMartin Matuska 28181ad8388SMartin Matuska case ISEQ_ERROR: 28281ad8388SMartin Matuska default: 28381ad8388SMartin Matuska return LZMA_PROG_ERROR; 28481ad8388SMartin Matuska } 28581ad8388SMartin Matuska 28681ad8388SMartin Matuska size_t in_pos = 0; 28781ad8388SMartin Matuska size_t out_pos = 0; 28881ad8388SMartin Matuska lzma_ret ret = strm->internal->next.code( 28981ad8388SMartin Matuska strm->internal->next.coder, strm->allocator, 29081ad8388SMartin Matuska strm->next_in, &in_pos, strm->avail_in, 29181ad8388SMartin Matuska strm->next_out, &out_pos, strm->avail_out, action); 29281ad8388SMartin Matuska 293c917796cSXin LI // Updating next_in and next_out has to be skipped when they are NULL 294c917796cSXin LI // to avoid null pointer + 0 (undefined behavior). Do this by checking 295c917796cSXin LI // in_pos > 0 and out_pos > 0 because this way NULL + non-zero (a bug) 296c917796cSXin LI // will get caught one way or other. 297c917796cSXin LI if (in_pos > 0) { 29881ad8388SMartin Matuska strm->next_in += in_pos; 29981ad8388SMartin Matuska strm->avail_in -= in_pos; 30081ad8388SMartin Matuska strm->total_in += in_pos; 301c917796cSXin LI } 30281ad8388SMartin Matuska 303c917796cSXin LI if (out_pos > 0) { 30481ad8388SMartin Matuska strm->next_out += out_pos; 30581ad8388SMartin Matuska strm->avail_out -= out_pos; 30681ad8388SMartin Matuska strm->total_out += out_pos; 307c917796cSXin LI } 30881ad8388SMartin Matuska 30981ad8388SMartin Matuska strm->internal->avail_in = strm->avail_in; 31081ad8388SMartin Matuska 31173ed8e77SXin LI switch (ret) { 31281ad8388SMartin Matuska case LZMA_OK: 31381ad8388SMartin Matuska // Don't return LZMA_BUF_ERROR when it happens the first time. 31481ad8388SMartin Matuska // This is to avoid returning LZMA_BUF_ERROR when avail_out 31581ad8388SMartin Matuska // was zero but still there was no more data left to written 31681ad8388SMartin Matuska // to next_out. 31781ad8388SMartin Matuska if (out_pos == 0 && in_pos == 0) { 31881ad8388SMartin Matuska if (strm->internal->allow_buf_error) 31981ad8388SMartin Matuska ret = LZMA_BUF_ERROR; 32081ad8388SMartin Matuska else 32181ad8388SMartin Matuska strm->internal->allow_buf_error = true; 32281ad8388SMartin Matuska } else { 32381ad8388SMartin Matuska strm->internal->allow_buf_error = false; 32481ad8388SMartin Matuska } 32581ad8388SMartin Matuska break; 32681ad8388SMartin Matuska 32753200025SRui Paulo case LZMA_TIMED_OUT: 32853200025SRui Paulo strm->internal->allow_buf_error = false; 32953200025SRui Paulo ret = LZMA_OK; 33053200025SRui Paulo break; 33153200025SRui Paulo 33273ed8e77SXin LI case LZMA_SEEK_NEEDED: 33373ed8e77SXin LI strm->internal->allow_buf_error = false; 33473ed8e77SXin LI 33573ed8e77SXin LI // If LZMA_FINISH was used, reset it back to the 33673ed8e77SXin LI // LZMA_RUN-based state so that new input can be supplied 33773ed8e77SXin LI // by the application. 33873ed8e77SXin LI if (strm->internal->sequence == ISEQ_FINISH) 33973ed8e77SXin LI strm->internal->sequence = ISEQ_RUN; 34073ed8e77SXin LI 34173ed8e77SXin LI break; 34273ed8e77SXin LI 34381ad8388SMartin Matuska case LZMA_STREAM_END: 34481ad8388SMartin Matuska if (strm->internal->sequence == ISEQ_SYNC_FLUSH 34553200025SRui Paulo || strm->internal->sequence == ISEQ_FULL_FLUSH 34653200025SRui Paulo || strm->internal->sequence 34753200025SRui Paulo == ISEQ_FULL_BARRIER) 34881ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 34981ad8388SMartin Matuska else 35081ad8388SMartin Matuska strm->internal->sequence = ISEQ_END; 35181ad8388SMartin Matuska 35281ad8388SMartin Matuska // Fall through 35381ad8388SMartin Matuska 35481ad8388SMartin Matuska case LZMA_NO_CHECK: 35581ad8388SMartin Matuska case LZMA_UNSUPPORTED_CHECK: 35681ad8388SMartin Matuska case LZMA_GET_CHECK: 35781ad8388SMartin Matuska case LZMA_MEMLIMIT_ERROR: 35881ad8388SMartin Matuska // Something else than LZMA_OK, but not a fatal error, 35981ad8388SMartin Matuska // that is, coding may be continued (except if ISEQ_END). 36081ad8388SMartin Matuska strm->internal->allow_buf_error = false; 36181ad8388SMartin Matuska break; 36281ad8388SMartin Matuska 36381ad8388SMartin Matuska default: 36481ad8388SMartin Matuska // All the other errors are fatal; coding cannot be continued. 36581ad8388SMartin Matuska assert(ret != LZMA_BUF_ERROR); 36681ad8388SMartin Matuska strm->internal->sequence = ISEQ_ERROR; 36781ad8388SMartin Matuska break; 36881ad8388SMartin Matuska } 36981ad8388SMartin Matuska 37081ad8388SMartin Matuska return ret; 37181ad8388SMartin Matuska } 37281ad8388SMartin Matuska 37381ad8388SMartin Matuska 37481ad8388SMartin Matuska extern LZMA_API(void) 37581ad8388SMartin Matuska lzma_end(lzma_stream *strm) 37681ad8388SMartin Matuska { 37781ad8388SMartin Matuska if (strm != NULL && strm->internal != NULL) { 37881ad8388SMartin Matuska lzma_next_end(&strm->internal->next, strm->allocator); 37981ad8388SMartin Matuska lzma_free(strm->internal, strm->allocator); 38081ad8388SMartin Matuska strm->internal = NULL; 38181ad8388SMartin Matuska } 38281ad8388SMartin Matuska 38381ad8388SMartin Matuska return; 38481ad8388SMartin Matuska } 38581ad8388SMartin Matuska 38681ad8388SMartin Matuska 3879e6bbe47SXin LI #ifdef HAVE_SYMBOL_VERSIONS_LINUX 3889e6bbe47SXin LI // This is for compatibility with binaries linked against liblzma that 3899e6bbe47SXin LI // has been patched with xz-5.2.2-compat-libs.patch from RHEL/CentOS 7. 3909e6bbe47SXin LI LZMA_SYMVER_API("lzma_get_progress@XZ_5.2.2", 3919e6bbe47SXin LI void, lzma_get_progress_522)(lzma_stream *strm, 3929e6bbe47SXin LI uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow 3939e6bbe47SXin LI __attribute__((__alias__("lzma_get_progress_52"))); 3949e6bbe47SXin LI 3959e6bbe47SXin LI LZMA_SYMVER_API("lzma_get_progress@@XZ_5.2", 3969e6bbe47SXin LI void, lzma_get_progress_52)(lzma_stream *strm, 3979e6bbe47SXin LI uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow; 3989e6bbe47SXin LI 3999e6bbe47SXin LI #define lzma_get_progress lzma_get_progress_52 4009e6bbe47SXin LI #endif 40153200025SRui Paulo extern LZMA_API(void) 40253200025SRui Paulo lzma_get_progress(lzma_stream *strm, 40353200025SRui Paulo uint64_t *progress_in, uint64_t *progress_out) 40453200025SRui Paulo { 40553200025SRui Paulo if (strm->internal->next.get_progress != NULL) { 40653200025SRui Paulo strm->internal->next.get_progress(strm->internal->next.coder, 40753200025SRui Paulo progress_in, progress_out); 40853200025SRui Paulo } else { 40953200025SRui Paulo *progress_in = strm->total_in; 41053200025SRui Paulo *progress_out = strm->total_out; 41153200025SRui Paulo } 41253200025SRui Paulo 41353200025SRui Paulo return; 41453200025SRui Paulo } 41553200025SRui Paulo 41653200025SRui Paulo 41781ad8388SMartin Matuska extern LZMA_API(lzma_check) 41881ad8388SMartin Matuska lzma_get_check(const lzma_stream *strm) 41981ad8388SMartin Matuska { 42081ad8388SMartin Matuska // Return LZMA_CHECK_NONE if we cannot know the check type. 42181ad8388SMartin Matuska // It's a bug in the application if this happens. 42281ad8388SMartin Matuska if (strm->internal->next.get_check == NULL) 42381ad8388SMartin Matuska return LZMA_CHECK_NONE; 42481ad8388SMartin Matuska 42581ad8388SMartin Matuska return strm->internal->next.get_check(strm->internal->next.coder); 42681ad8388SMartin Matuska } 42781ad8388SMartin Matuska 42881ad8388SMartin Matuska 42981ad8388SMartin Matuska extern LZMA_API(uint64_t) 43081ad8388SMartin Matuska lzma_memusage(const lzma_stream *strm) 43181ad8388SMartin Matuska { 43281ad8388SMartin Matuska uint64_t memusage; 43381ad8388SMartin Matuska uint64_t old_memlimit; 43481ad8388SMartin Matuska 43581ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 43681ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 43781ad8388SMartin Matuska || strm->internal->next.memconfig( 43881ad8388SMartin Matuska strm->internal->next.coder, 43981ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 44081ad8388SMartin Matuska return 0; 44181ad8388SMartin Matuska 44281ad8388SMartin Matuska return memusage; 44381ad8388SMartin Matuska } 44481ad8388SMartin Matuska 44581ad8388SMartin Matuska 44681ad8388SMartin Matuska extern LZMA_API(uint64_t) 44781ad8388SMartin Matuska lzma_memlimit_get(const lzma_stream *strm) 44881ad8388SMartin Matuska { 44981ad8388SMartin Matuska uint64_t old_memlimit; 45081ad8388SMartin Matuska uint64_t memusage; 45181ad8388SMartin Matuska 45281ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 45381ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 45481ad8388SMartin Matuska || strm->internal->next.memconfig( 45581ad8388SMartin Matuska strm->internal->next.coder, 45681ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 45781ad8388SMartin Matuska return 0; 45881ad8388SMartin Matuska 45981ad8388SMartin Matuska return old_memlimit; 46081ad8388SMartin Matuska } 46181ad8388SMartin Matuska 46281ad8388SMartin Matuska 46381ad8388SMartin Matuska extern LZMA_API(lzma_ret) 46481ad8388SMartin Matuska lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) 46581ad8388SMartin Matuska { 46681ad8388SMartin Matuska // Dummy variables to simplify memconfig functions 46781ad8388SMartin Matuska uint64_t old_memlimit; 46881ad8388SMartin Matuska uint64_t memusage; 46981ad8388SMartin Matuska 47081ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 47181ad8388SMartin Matuska || strm->internal->next.memconfig == NULL) 47281ad8388SMartin Matuska return LZMA_PROG_ERROR; 47381ad8388SMartin Matuska 474b71a5db3SXin LI // Zero is a special value that cannot be used as an actual limit. 475b71a5db3SXin LI // If 0 was specified, use 1 instead. 476b71a5db3SXin LI if (new_memlimit == 0) 477b71a5db3SXin LI new_memlimit = 1; 47881ad8388SMartin Matuska 47981ad8388SMartin Matuska return strm->internal->next.memconfig(strm->internal->next.coder, 48081ad8388SMartin Matuska &memusage, &old_memlimit, new_memlimit); 48181ad8388SMartin Matuska } 482