1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file common.h 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) 39292588Sdelphijlzma_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 56292588Sdelphijextern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) 57292588Sdelphijlzma_alloc_zero(size_t size, const lzma_allocator *allocator) 58292588Sdelphij{ 59292588Sdelphij // Some calloc() variants return NULL if called with size == 0. 60292588Sdelphij if (size == 0) 61292588Sdelphij size = 1; 62292588Sdelphij 63292588Sdelphij void *ptr; 64292588Sdelphij 65292588Sdelphij if (allocator != NULL && allocator->alloc != NULL) { 66292588Sdelphij ptr = allocator->alloc(allocator->opaque, 1, size); 67292588Sdelphij if (ptr != NULL) 68292588Sdelphij memzero(ptr, size); 69292588Sdelphij } else { 70292588Sdelphij ptr = calloc(1, size); 71292588Sdelphij } 72292588Sdelphij 73292588Sdelphij return ptr; 74292588Sdelphij} 75292588Sdelphij 76292588Sdelphij 77207753Smmextern void 78292588Sdelphijlzma_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 102207753Smm memcpy(out + *out_pos, in + *in_pos, copy_size); 103207753Smm 104207753Smm *in_pos += copy_size; 105207753Smm *out_pos += copy_size; 106207753Smm 107207753Smm return copy_size; 108207753Smm} 109207753Smm 110207753Smm 111207753Smmextern lzma_ret 112292588Sdelphijlzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, 113207753Smm const lzma_filter_info *filters) 114207753Smm{ 115207753Smm lzma_next_coder_init(filters[0].init, next, allocator); 116207753Smm next->id = filters[0].id; 117207753Smm return filters[0].init == NULL 118207753Smm ? LZMA_OK : filters[0].init(next, allocator, filters); 119207753Smm} 120207753Smm 121207753Smm 122207753Smmextern lzma_ret 123292588Sdelphijlzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator, 124207753Smm const lzma_filter *reversed_filters) 125207753Smm{ 126207753Smm // Check that the application isn't trying to change the Filter ID. 127207753Smm // End of filters is indicated with LZMA_VLI_UNKNOWN in both 128207753Smm // reversed_filters[0].id and next->id. 129207753Smm if (reversed_filters[0].id != next->id) 130207753Smm return LZMA_PROG_ERROR; 131207753Smm 132207753Smm if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) 133207753Smm return LZMA_OK; 134207753Smm 135207753Smm assert(next->update != NULL); 136207753Smm return next->update(next->coder, allocator, NULL, reversed_filters); 137207753Smm} 138207753Smm 139207753Smm 140207753Smmextern void 141292588Sdelphijlzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator) 142207753Smm{ 143207753Smm if (next->init != (uintptr_t)(NULL)) { 144207753Smm // To avoid tiny end functions that simply call 145207753Smm // lzma_free(coder, allocator), we allow leaving next->end 146207753Smm // NULL and call lzma_free() here. 147207753Smm if (next->end != NULL) 148207753Smm next->end(next->coder, allocator); 149207753Smm else 150207753Smm lzma_free(next->coder, allocator); 151207753Smm 152207753Smm // Reset the variables so the we don't accidentally think 153207753Smm // that it is an already initialized coder. 154207753Smm *next = LZMA_NEXT_CODER_INIT; 155207753Smm } 156207753Smm 157207753Smm return; 158207753Smm} 159207753Smm 160207753Smm 161207753Smm////////////////////////////////////// 162207753Smm// External to internal API wrapper // 163207753Smm////////////////////////////////////// 164207753Smm 165207753Smmextern lzma_ret 166207753Smmlzma_strm_init(lzma_stream *strm) 167207753Smm{ 168207753Smm if (strm == NULL) 169207753Smm return LZMA_PROG_ERROR; 170207753Smm 171207753Smm if (strm->internal == NULL) { 172207753Smm strm->internal = lzma_alloc(sizeof(lzma_internal), 173207753Smm strm->allocator); 174207753Smm if (strm->internal == NULL) 175207753Smm return LZMA_MEM_ERROR; 176207753Smm 177207753Smm strm->internal->next = LZMA_NEXT_CODER_INIT; 178207753Smm } 179207753Smm 180292588Sdelphij memzero(strm->internal->supported_actions, 181292588Sdelphij sizeof(strm->internal->supported_actions)); 182207753Smm strm->internal->sequence = ISEQ_RUN; 183207753Smm strm->internal->allow_buf_error = false; 184207753Smm 185207753Smm strm->total_in = 0; 186207753Smm strm->total_out = 0; 187207753Smm 188207753Smm return LZMA_OK; 189207753Smm} 190207753Smm 191207753Smm 192207753Smmextern LZMA_API(lzma_ret) 193207753Smmlzma_code(lzma_stream *strm, lzma_action action) 194207753Smm{ 195207753Smm // Sanity checks 196207753Smm if ((strm->next_in == NULL && strm->avail_in != 0) 197207753Smm || (strm->next_out == NULL && strm->avail_out != 0) 198207753Smm || strm->internal == NULL 199207753Smm || strm->internal->next.code == NULL 200292588Sdelphij || (unsigned int)(action) > LZMA_ACTION_MAX 201207753Smm || !strm->internal->supported_actions[action]) 202207753Smm return LZMA_PROG_ERROR; 203207753Smm 204215187Smm // Check if unsupported members have been set to non-zero or non-NULL, 205215187Smm // which would indicate that some new feature is wanted. 206215187Smm if (strm->reserved_ptr1 != NULL 207215187Smm || strm->reserved_ptr2 != NULL 208215187Smm || strm->reserved_ptr3 != NULL 209215187Smm || strm->reserved_ptr4 != NULL 210215187Smm || strm->reserved_int1 != 0 211215187Smm || strm->reserved_int2 != 0 212215187Smm || strm->reserved_int3 != 0 213215187Smm || strm->reserved_int4 != 0 214215187Smm || strm->reserved_enum1 != LZMA_RESERVED_ENUM 215215187Smm || strm->reserved_enum2 != LZMA_RESERVED_ENUM) 216215187Smm return LZMA_OPTIONS_ERROR; 217215187Smm 218207753Smm switch (strm->internal->sequence) { 219207753Smm case ISEQ_RUN: 220207753Smm switch (action) { 221207753Smm case LZMA_RUN: 222207753Smm break; 223207753Smm 224207753Smm case LZMA_SYNC_FLUSH: 225207753Smm strm->internal->sequence = ISEQ_SYNC_FLUSH; 226207753Smm break; 227207753Smm 228207753Smm case LZMA_FULL_FLUSH: 229207753Smm strm->internal->sequence = ISEQ_FULL_FLUSH; 230207753Smm break; 231207753Smm 232207753Smm case LZMA_FINISH: 233207753Smm strm->internal->sequence = ISEQ_FINISH; 234207753Smm break; 235292588Sdelphij 236292588Sdelphij case LZMA_FULL_BARRIER: 237292588Sdelphij strm->internal->sequence = ISEQ_FULL_BARRIER; 238292588Sdelphij break; 239207753Smm } 240207753Smm 241207753Smm break; 242207753Smm 243207753Smm case ISEQ_SYNC_FLUSH: 244207753Smm // The same action must be used until we return 245207753Smm // LZMA_STREAM_END, and the amount of input must not change. 246207753Smm if (action != LZMA_SYNC_FLUSH 247207753Smm || strm->internal->avail_in != strm->avail_in) 248207753Smm return LZMA_PROG_ERROR; 249207753Smm 250207753Smm break; 251207753Smm 252207753Smm case ISEQ_FULL_FLUSH: 253207753Smm if (action != LZMA_FULL_FLUSH 254207753Smm || strm->internal->avail_in != strm->avail_in) 255207753Smm return LZMA_PROG_ERROR; 256207753Smm 257207753Smm break; 258207753Smm 259207753Smm case ISEQ_FINISH: 260207753Smm if (action != LZMA_FINISH 261207753Smm || strm->internal->avail_in != strm->avail_in) 262207753Smm return LZMA_PROG_ERROR; 263207753Smm 264207753Smm break; 265207753Smm 266292588Sdelphij case ISEQ_FULL_BARRIER: 267292588Sdelphij if (action != LZMA_FULL_BARRIER 268292588Sdelphij || strm->internal->avail_in != strm->avail_in) 269292588Sdelphij return LZMA_PROG_ERROR; 270292588Sdelphij 271292588Sdelphij break; 272292588Sdelphij 273207753Smm case ISEQ_END: 274207753Smm return LZMA_STREAM_END; 275207753Smm 276207753Smm case ISEQ_ERROR: 277207753Smm default: 278207753Smm return LZMA_PROG_ERROR; 279207753Smm } 280207753Smm 281207753Smm size_t in_pos = 0; 282207753Smm size_t out_pos = 0; 283207753Smm lzma_ret ret = strm->internal->next.code( 284207753Smm strm->internal->next.coder, strm->allocator, 285207753Smm strm->next_in, &in_pos, strm->avail_in, 286207753Smm strm->next_out, &out_pos, strm->avail_out, action); 287207753Smm 288207753Smm strm->next_in += in_pos; 289207753Smm strm->avail_in -= in_pos; 290207753Smm strm->total_in += in_pos; 291207753Smm 292207753Smm strm->next_out += out_pos; 293207753Smm strm->avail_out -= out_pos; 294207753Smm strm->total_out += out_pos; 295207753Smm 296207753Smm strm->internal->avail_in = strm->avail_in; 297207753Smm 298292588Sdelphij // Cast is needed to silence a warning about LZMA_TIMED_OUT, which 299292588Sdelphij // isn't part of lzma_ret enumeration. 300292588Sdelphij switch ((unsigned int)(ret)) { 301207753Smm case LZMA_OK: 302207753Smm // Don't return LZMA_BUF_ERROR when it happens the first time. 303207753Smm // This is to avoid returning LZMA_BUF_ERROR when avail_out 304207753Smm // was zero but still there was no more data left to written 305207753Smm // to next_out. 306207753Smm if (out_pos == 0 && in_pos == 0) { 307207753Smm if (strm->internal->allow_buf_error) 308207753Smm ret = LZMA_BUF_ERROR; 309207753Smm else 310207753Smm strm->internal->allow_buf_error = true; 311207753Smm } else { 312207753Smm strm->internal->allow_buf_error = false; 313207753Smm } 314207753Smm break; 315207753Smm 316292588Sdelphij case LZMA_TIMED_OUT: 317292588Sdelphij strm->internal->allow_buf_error = false; 318292588Sdelphij ret = LZMA_OK; 319292588Sdelphij break; 320292588Sdelphij 321207753Smm case LZMA_STREAM_END: 322207753Smm if (strm->internal->sequence == ISEQ_SYNC_FLUSH 323292588Sdelphij || strm->internal->sequence == ISEQ_FULL_FLUSH 324292588Sdelphij || strm->internal->sequence 325292588Sdelphij == ISEQ_FULL_BARRIER) 326207753Smm strm->internal->sequence = ISEQ_RUN; 327207753Smm else 328207753Smm strm->internal->sequence = ISEQ_END; 329207753Smm 330207753Smm // Fall through 331207753Smm 332207753Smm case LZMA_NO_CHECK: 333207753Smm case LZMA_UNSUPPORTED_CHECK: 334207753Smm case LZMA_GET_CHECK: 335207753Smm case LZMA_MEMLIMIT_ERROR: 336207753Smm // Something else than LZMA_OK, but not a fatal error, 337207753Smm // that is, coding may be continued (except if ISEQ_END). 338207753Smm strm->internal->allow_buf_error = false; 339207753Smm break; 340207753Smm 341207753Smm default: 342207753Smm // All the other errors are fatal; coding cannot be continued. 343207753Smm assert(ret != LZMA_BUF_ERROR); 344207753Smm strm->internal->sequence = ISEQ_ERROR; 345207753Smm break; 346207753Smm } 347207753Smm 348207753Smm return ret; 349207753Smm} 350207753Smm 351207753Smm 352207753Smmextern LZMA_API(void) 353207753Smmlzma_end(lzma_stream *strm) 354207753Smm{ 355207753Smm if (strm != NULL && strm->internal != NULL) { 356207753Smm lzma_next_end(&strm->internal->next, strm->allocator); 357207753Smm lzma_free(strm->internal, strm->allocator); 358207753Smm strm->internal = NULL; 359207753Smm } 360207753Smm 361207753Smm return; 362207753Smm} 363207753Smm 364207753Smm 365292588Sdelphijextern LZMA_API(void) 366292588Sdelphijlzma_get_progress(lzma_stream *strm, 367292588Sdelphij uint64_t *progress_in, uint64_t *progress_out) 368292588Sdelphij{ 369292588Sdelphij if (strm->internal->next.get_progress != NULL) { 370292588Sdelphij strm->internal->next.get_progress(strm->internal->next.coder, 371292588Sdelphij progress_in, progress_out); 372292588Sdelphij } else { 373292588Sdelphij *progress_in = strm->total_in; 374292588Sdelphij *progress_out = strm->total_out; 375292588Sdelphij } 376292588Sdelphij 377292588Sdelphij return; 378292588Sdelphij} 379292588Sdelphij 380292588Sdelphij 381207753Smmextern LZMA_API(lzma_check) 382207753Smmlzma_get_check(const lzma_stream *strm) 383207753Smm{ 384207753Smm // Return LZMA_CHECK_NONE if we cannot know the check type. 385207753Smm // It's a bug in the application if this happens. 386207753Smm if (strm->internal->next.get_check == NULL) 387207753Smm return LZMA_CHECK_NONE; 388207753Smm 389207753Smm return strm->internal->next.get_check(strm->internal->next.coder); 390207753Smm} 391207753Smm 392207753Smm 393207753Smmextern LZMA_API(uint64_t) 394207753Smmlzma_memusage(const lzma_stream *strm) 395207753Smm{ 396207753Smm uint64_t memusage; 397207753Smm uint64_t old_memlimit; 398207753Smm 399207753Smm if (strm == NULL || strm->internal == NULL 400207753Smm || strm->internal->next.memconfig == NULL 401207753Smm || strm->internal->next.memconfig( 402207753Smm strm->internal->next.coder, 403207753Smm &memusage, &old_memlimit, 0) != LZMA_OK) 404207753Smm return 0; 405207753Smm 406207753Smm return memusage; 407207753Smm} 408207753Smm 409207753Smm 410207753Smmextern LZMA_API(uint64_t) 411207753Smmlzma_memlimit_get(const lzma_stream *strm) 412207753Smm{ 413207753Smm uint64_t old_memlimit; 414207753Smm uint64_t memusage; 415207753Smm 416207753Smm if (strm == NULL || strm->internal == NULL 417207753Smm || strm->internal->next.memconfig == NULL 418207753Smm || strm->internal->next.memconfig( 419207753Smm strm->internal->next.coder, 420207753Smm &memusage, &old_memlimit, 0) != LZMA_OK) 421207753Smm return 0; 422207753Smm 423207753Smm return old_memlimit; 424207753Smm} 425207753Smm 426207753Smm 427207753Smmextern LZMA_API(lzma_ret) 428207753Smmlzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) 429207753Smm{ 430207753Smm // Dummy variables to simplify memconfig functions 431207753Smm uint64_t old_memlimit; 432207753Smm uint64_t memusage; 433207753Smm 434207753Smm if (strm == NULL || strm->internal == NULL 435207753Smm || strm->internal->next.memconfig == NULL) 436207753Smm return LZMA_PROG_ERROR; 437207753Smm 438207753Smm if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE) 439207753Smm return LZMA_MEMLIMIT_ERROR; 440207753Smm 441207753Smm return strm->internal->next.memconfig(strm->internal->next.coder, 442207753Smm &memusage, &old_memlimit, new_memlimit); 443207753Smm} 444