1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3360523Sdelphij/// \file common.c 4207753Smm/// \brief Common functions needed in many places in liblzma 5207753Smm// 6207753Smm// Author: Lasse Collin 7207753Smm// 8207753Smm// This file has been put into the public domain. 9207753Smm// You can do whatever you want with this file. 10207753Smm// 11207753Smm/////////////////////////////////////////////////////////////////////////////// 12207753Smm 13207753Smm#include "common.h" 14207753Smm 15207753Smm 16207753Smm///////////// 17207753Smm// Version // 18207753Smm///////////// 19207753Smm 20207753Smmextern LZMA_API(uint32_t) 21207753Smmlzma_version_number(void) 22207753Smm{ 23207753Smm return LZMA_VERSION; 24207753Smm} 25207753Smm 26207753Smm 27207753Smmextern LZMA_API(const char *) 28207753Smmlzma_version_string(void) 29207753Smm{ 30207753Smm return LZMA_VERSION_STRING; 31207753Smm} 32207753Smm 33207753Smm 34207753Smm/////////////////////// 35207753Smm// Memory allocation // 36207753Smm/////////////////////// 37207753Smm 38223935Smmextern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) 39278433Srpaulolzma_alloc(size_t size, const lzma_allocator *allocator) 40207753Smm{ 41207753Smm // Some malloc() variants return NULL if called with size == 0. 42207753Smm if (size == 0) 43207753Smm size = 1; 44207753Smm 45207753Smm void *ptr; 46207753Smm 47207753Smm if (allocator != NULL && allocator->alloc != NULL) 48207753Smm ptr = allocator->alloc(allocator->opaque, 1, size); 49207753Smm else 50207753Smm ptr = malloc(size); 51207753Smm 52207753Smm return ptr; 53207753Smm} 54207753Smm 55207753Smm 56278433Srpauloextern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) 57278433Srpaulolzma_alloc_zero(size_t size, const lzma_allocator *allocator) 58278433Srpaulo{ 59278433Srpaulo // Some calloc() variants return NULL if called with size == 0. 60278433Srpaulo if (size == 0) 61278433Srpaulo size = 1; 62278433Srpaulo 63278433Srpaulo void *ptr; 64278433Srpaulo 65278433Srpaulo if (allocator != NULL && allocator->alloc != NULL) { 66278433Srpaulo ptr = allocator->alloc(allocator->opaque, 1, size); 67278433Srpaulo if (ptr != NULL) 68278433Srpaulo memzero(ptr, size); 69278433Srpaulo } else { 70278433Srpaulo ptr = calloc(1, size); 71278433Srpaulo } 72278433Srpaulo 73278433Srpaulo return ptr; 74278433Srpaulo} 75278433Srpaulo 76278433Srpaulo 77207753Smmextern void 78278433Srpaulolzma_free(void *ptr, const lzma_allocator *allocator) 79207753Smm{ 80207753Smm if (allocator != NULL && allocator->free != NULL) 81207753Smm allocator->free(allocator->opaque, ptr); 82207753Smm else 83207753Smm free(ptr); 84207753Smm 85207753Smm return; 86207753Smm} 87207753Smm 88207753Smm 89207753Smm////////// 90207753Smm// Misc // 91207753Smm////////// 92207753Smm 93207753Smmextern size_t 94207753Smmlzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, 95207753Smm size_t in_size, uint8_t *restrict out, 96207753Smm size_t *restrict out_pos, size_t out_size) 97207753Smm{ 98207753Smm const size_t in_avail = in_size - *in_pos; 99207753Smm const size_t out_avail = out_size - *out_pos; 100213700Smm const size_t copy_size = my_min(in_avail, out_avail); 101207753Smm 102360523Sdelphij // Call memcpy() only if there is something to copy. If there is 103360523Sdelphij // nothing to copy, in or out might be NULL and then the memcpy() 104360523Sdelphij // call would trigger undefined behavior. 105360523Sdelphij if (copy_size > 0) 106360523Sdelphij memcpy(out + *out_pos, in + *in_pos, copy_size); 107207753Smm 108207753Smm *in_pos += copy_size; 109207753Smm *out_pos += copy_size; 110207753Smm 111207753Smm return copy_size; 112207753Smm} 113207753Smm 114207753Smm 115207753Smmextern lzma_ret 116278433Srpaulolzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, 117207753Smm const lzma_filter_info *filters) 118207753Smm{ 119207753Smm lzma_next_coder_init(filters[0].init, next, allocator); 120207753Smm next->id = filters[0].id; 121207753Smm return filters[0].init == NULL 122207753Smm ? LZMA_OK : filters[0].init(next, allocator, filters); 123207753Smm} 124207753Smm 125207753Smm 126207753Smmextern lzma_ret 127278433Srpaulolzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator, 128207753Smm const lzma_filter *reversed_filters) 129207753Smm{ 130207753Smm // Check that the application isn't trying to change the Filter ID. 131207753Smm // End of filters is indicated with LZMA_VLI_UNKNOWN in both 132207753Smm // reversed_filters[0].id and next->id. 133207753Smm if (reversed_filters[0].id != next->id) 134207753Smm return LZMA_PROG_ERROR; 135207753Smm 136207753Smm if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) 137207753Smm return LZMA_OK; 138207753Smm 139207753Smm assert(next->update != NULL); 140207753Smm return next->update(next->coder, allocator, NULL, reversed_filters); 141207753Smm} 142207753Smm 143207753Smm 144207753Smmextern void 145278433Srpaulolzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator) 146207753Smm{ 147207753Smm if (next->init != (uintptr_t)(NULL)) { 148207753Smm // To avoid tiny end functions that simply call 149207753Smm // lzma_free(coder, allocator), we allow leaving next->end 150207753Smm // NULL and call lzma_free() here. 151207753Smm if (next->end != NULL) 152207753Smm next->end(next->coder, allocator); 153207753Smm else 154207753Smm lzma_free(next->coder, allocator); 155207753Smm 156207753Smm // Reset the variables so the we don't accidentally think 157207753Smm // that it is an already initialized coder. 158207753Smm *next = LZMA_NEXT_CODER_INIT; 159207753Smm } 160207753Smm 161207753Smm return; 162207753Smm} 163207753Smm 164207753Smm 165207753Smm////////////////////////////////////// 166207753Smm// External to internal API wrapper // 167207753Smm////////////////////////////////////// 168207753Smm 169207753Smmextern lzma_ret 170207753Smmlzma_strm_init(lzma_stream *strm) 171207753Smm{ 172207753Smm if (strm == NULL) 173207753Smm return LZMA_PROG_ERROR; 174207753Smm 175207753Smm if (strm->internal == NULL) { 176207753Smm strm->internal = lzma_alloc(sizeof(lzma_internal), 177207753Smm strm->allocator); 178207753Smm if (strm->internal == NULL) 179207753Smm return LZMA_MEM_ERROR; 180207753Smm 181207753Smm strm->internal->next = LZMA_NEXT_CODER_INIT; 182207753Smm } 183207753Smm 184278433Srpaulo memzero(strm->internal->supported_actions, 185278433Srpaulo sizeof(strm->internal->supported_actions)); 186207753Smm strm->internal->sequence = ISEQ_RUN; 187207753Smm strm->internal->allow_buf_error = false; 188207753Smm 189207753Smm strm->total_in = 0; 190207753Smm strm->total_out = 0; 191207753Smm 192207753Smm return LZMA_OK; 193207753Smm} 194207753Smm 195207753Smm 196207753Smmextern LZMA_API(lzma_ret) 197207753Smmlzma_code(lzma_stream *strm, lzma_action action) 198207753Smm{ 199207753Smm // Sanity checks 200207753Smm if ((strm->next_in == NULL && strm->avail_in != 0) 201207753Smm || (strm->next_out == NULL && strm->avail_out != 0) 202207753Smm || strm->internal == NULL 203207753Smm || strm->internal->next.code == NULL 204278433Srpaulo || (unsigned int)(action) > LZMA_ACTION_MAX 205207753Smm || !strm->internal->supported_actions[action]) 206207753Smm return LZMA_PROG_ERROR; 207207753Smm 208215187Smm // Check if unsupported members have been set to non-zero or non-NULL, 209215187Smm // which would indicate that some new feature is wanted. 210215187Smm if (strm->reserved_ptr1 != NULL 211215187Smm || strm->reserved_ptr2 != NULL 212215187Smm || strm->reserved_ptr3 != NULL 213215187Smm || strm->reserved_ptr4 != NULL 214215187Smm || strm->reserved_int1 != 0 215215187Smm || strm->reserved_int2 != 0 216215187Smm || strm->reserved_int3 != 0 217215187Smm || strm->reserved_int4 != 0 218215187Smm || strm->reserved_enum1 != LZMA_RESERVED_ENUM 219215187Smm || strm->reserved_enum2 != LZMA_RESERVED_ENUM) 220215187Smm return LZMA_OPTIONS_ERROR; 221215187Smm 222207753Smm switch (strm->internal->sequence) { 223207753Smm case ISEQ_RUN: 224207753Smm switch (action) { 225207753Smm case LZMA_RUN: 226207753Smm break; 227207753Smm 228207753Smm case LZMA_SYNC_FLUSH: 229207753Smm strm->internal->sequence = ISEQ_SYNC_FLUSH; 230207753Smm break; 231207753Smm 232207753Smm case LZMA_FULL_FLUSH: 233207753Smm strm->internal->sequence = ISEQ_FULL_FLUSH; 234207753Smm break; 235207753Smm 236207753Smm case LZMA_FINISH: 237207753Smm strm->internal->sequence = ISEQ_FINISH; 238207753Smm break; 239278433Srpaulo 240278433Srpaulo case LZMA_FULL_BARRIER: 241278433Srpaulo strm->internal->sequence = ISEQ_FULL_BARRIER; 242278433Srpaulo break; 243207753Smm } 244207753Smm 245207753Smm break; 246207753Smm 247207753Smm case ISEQ_SYNC_FLUSH: 248207753Smm // The same action must be used until we return 249207753Smm // LZMA_STREAM_END, and the amount of input must not change. 250207753Smm if (action != LZMA_SYNC_FLUSH 251207753Smm || strm->internal->avail_in != strm->avail_in) 252207753Smm return LZMA_PROG_ERROR; 253207753Smm 254207753Smm break; 255207753Smm 256207753Smm case ISEQ_FULL_FLUSH: 257207753Smm if (action != LZMA_FULL_FLUSH 258207753Smm || strm->internal->avail_in != strm->avail_in) 259207753Smm return LZMA_PROG_ERROR; 260207753Smm 261207753Smm break; 262207753Smm 263207753Smm case ISEQ_FINISH: 264207753Smm if (action != LZMA_FINISH 265207753Smm || strm->internal->avail_in != strm->avail_in) 266207753Smm return LZMA_PROG_ERROR; 267207753Smm 268207753Smm break; 269207753Smm 270278433Srpaulo case ISEQ_FULL_BARRIER: 271278433Srpaulo if (action != LZMA_FULL_BARRIER 272278433Srpaulo || strm->internal->avail_in != strm->avail_in) 273278433Srpaulo return LZMA_PROG_ERROR; 274278433Srpaulo 275278433Srpaulo break; 276278433Srpaulo 277207753Smm case ISEQ_END: 278207753Smm return LZMA_STREAM_END; 279207753Smm 280207753Smm case ISEQ_ERROR: 281207753Smm default: 282207753Smm return LZMA_PROG_ERROR; 283207753Smm } 284207753Smm 285207753Smm size_t in_pos = 0; 286207753Smm size_t out_pos = 0; 287207753Smm lzma_ret ret = strm->internal->next.code( 288207753Smm strm->internal->next.coder, strm->allocator, 289207753Smm strm->next_in, &in_pos, strm->avail_in, 290207753Smm strm->next_out, &out_pos, strm->avail_out, action); 291207753Smm 292207753Smm strm->next_in += in_pos; 293207753Smm strm->avail_in -= in_pos; 294207753Smm strm->total_in += in_pos; 295207753Smm 296207753Smm strm->next_out += out_pos; 297207753Smm strm->avail_out -= out_pos; 298207753Smm strm->total_out += out_pos; 299207753Smm 300207753Smm strm->internal->avail_in = strm->avail_in; 301207753Smm 302278433Srpaulo // Cast is needed to silence a warning about LZMA_TIMED_OUT, which 303278433Srpaulo // isn't part of lzma_ret enumeration. 304278433Srpaulo switch ((unsigned int)(ret)) { 305207753Smm case LZMA_OK: 306207753Smm // Don't return LZMA_BUF_ERROR when it happens the first time. 307207753Smm // This is to avoid returning LZMA_BUF_ERROR when avail_out 308207753Smm // was zero but still there was no more data left to written 309207753Smm // to next_out. 310207753Smm if (out_pos == 0 && in_pos == 0) { 311207753Smm if (strm->internal->allow_buf_error) 312207753Smm ret = LZMA_BUF_ERROR; 313207753Smm else 314207753Smm strm->internal->allow_buf_error = true; 315207753Smm } else { 316207753Smm strm->internal->allow_buf_error = false; 317207753Smm } 318207753Smm break; 319207753Smm 320278433Srpaulo case LZMA_TIMED_OUT: 321278433Srpaulo strm->internal->allow_buf_error = false; 322278433Srpaulo ret = LZMA_OK; 323278433Srpaulo break; 324278433Srpaulo 325207753Smm case LZMA_STREAM_END: 326207753Smm if (strm->internal->sequence == ISEQ_SYNC_FLUSH 327278433Srpaulo || strm->internal->sequence == ISEQ_FULL_FLUSH 328278433Srpaulo || strm->internal->sequence 329278433Srpaulo == ISEQ_FULL_BARRIER) 330207753Smm strm->internal->sequence = ISEQ_RUN; 331207753Smm else 332207753Smm strm->internal->sequence = ISEQ_END; 333207753Smm 334207753Smm // Fall through 335207753Smm 336207753Smm case LZMA_NO_CHECK: 337207753Smm case LZMA_UNSUPPORTED_CHECK: 338207753Smm case LZMA_GET_CHECK: 339207753Smm case LZMA_MEMLIMIT_ERROR: 340207753Smm // Something else than LZMA_OK, but not a fatal error, 341207753Smm // that is, coding may be continued (except if ISEQ_END). 342207753Smm strm->internal->allow_buf_error = false; 343207753Smm break; 344207753Smm 345207753Smm default: 346207753Smm // All the other errors are fatal; coding cannot be continued. 347207753Smm assert(ret != LZMA_BUF_ERROR); 348207753Smm strm->internal->sequence = ISEQ_ERROR; 349207753Smm break; 350207753Smm } 351207753Smm 352207753Smm return ret; 353207753Smm} 354207753Smm 355207753Smm 356207753Smmextern LZMA_API(void) 357207753Smmlzma_end(lzma_stream *strm) 358207753Smm{ 359207753Smm if (strm != NULL && strm->internal != NULL) { 360207753Smm lzma_next_end(&strm->internal->next, strm->allocator); 361207753Smm lzma_free(strm->internal, strm->allocator); 362207753Smm strm->internal = NULL; 363207753Smm } 364207753Smm 365207753Smm return; 366207753Smm} 367207753Smm 368207753Smm 369278433Srpauloextern LZMA_API(void) 370278433Srpaulolzma_get_progress(lzma_stream *strm, 371278433Srpaulo uint64_t *progress_in, uint64_t *progress_out) 372278433Srpaulo{ 373278433Srpaulo if (strm->internal->next.get_progress != NULL) { 374278433Srpaulo strm->internal->next.get_progress(strm->internal->next.coder, 375278433Srpaulo progress_in, progress_out); 376278433Srpaulo } else { 377278433Srpaulo *progress_in = strm->total_in; 378278433Srpaulo *progress_out = strm->total_out; 379278433Srpaulo } 380278433Srpaulo 381278433Srpaulo return; 382278433Srpaulo} 383278433Srpaulo 384278433Srpaulo 385207753Smmextern LZMA_API(lzma_check) 386207753Smmlzma_get_check(const lzma_stream *strm) 387207753Smm{ 388207753Smm // Return LZMA_CHECK_NONE if we cannot know the check type. 389207753Smm // It's a bug in the application if this happens. 390207753Smm if (strm->internal->next.get_check == NULL) 391207753Smm return LZMA_CHECK_NONE; 392207753Smm 393207753Smm return strm->internal->next.get_check(strm->internal->next.coder); 394207753Smm} 395207753Smm 396207753Smm 397207753Smmextern LZMA_API(uint64_t) 398207753Smmlzma_memusage(const lzma_stream *strm) 399207753Smm{ 400207753Smm uint64_t memusage; 401207753Smm uint64_t old_memlimit; 402207753Smm 403207753Smm if (strm == NULL || strm->internal == NULL 404207753Smm || strm->internal->next.memconfig == NULL 405207753Smm || strm->internal->next.memconfig( 406207753Smm strm->internal->next.coder, 407207753Smm &memusage, &old_memlimit, 0) != LZMA_OK) 408207753Smm return 0; 409207753Smm 410207753Smm return memusage; 411207753Smm} 412207753Smm 413207753Smm 414207753Smmextern LZMA_API(uint64_t) 415207753Smmlzma_memlimit_get(const lzma_stream *strm) 416207753Smm{ 417207753Smm uint64_t old_memlimit; 418207753Smm uint64_t memusage; 419207753Smm 420207753Smm if (strm == NULL || strm->internal == NULL 421207753Smm || strm->internal->next.memconfig == NULL 422207753Smm || strm->internal->next.memconfig( 423207753Smm strm->internal->next.coder, 424207753Smm &memusage, &old_memlimit, 0) != LZMA_OK) 425207753Smm return 0; 426207753Smm 427207753Smm return old_memlimit; 428207753Smm} 429207753Smm 430207753Smm 431207753Smmextern LZMA_API(lzma_ret) 432207753Smmlzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) 433207753Smm{ 434207753Smm // Dummy variables to simplify memconfig functions 435207753Smm uint64_t old_memlimit; 436207753Smm uint64_t memusage; 437207753Smm 438207753Smm if (strm == NULL || strm->internal == NULL 439207753Smm || strm->internal->next.memconfig == NULL) 440207753Smm return LZMA_PROG_ERROR; 441207753Smm 442334607Sdelphij // Zero is a special value that cannot be used as an actual limit. 443334607Sdelphij // If 0 was specified, use 1 instead. 444334607Sdelphij if (new_memlimit == 0) 445334607Sdelphij new_memlimit = 1; 446207753Smm 447207753Smm return strm->internal->next.memconfig(strm->internal->next.coder, 448207753Smm &memusage, &old_memlimit, new_memlimit); 449207753Smm} 450