1*81ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 2*81ad8388SMartin Matuska // 3*81ad8388SMartin Matuska /// \file common.h 4*81ad8388SMartin Matuska /// \brief Common functions needed in many places in liblzma 5*81ad8388SMartin Matuska // 6*81ad8388SMartin Matuska // Author: Lasse Collin 7*81ad8388SMartin Matuska // 8*81ad8388SMartin Matuska // This file has been put into the public domain. 9*81ad8388SMartin Matuska // You can do whatever you want with this file. 10*81ad8388SMartin Matuska // 11*81ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 12*81ad8388SMartin Matuska 13*81ad8388SMartin Matuska #include "common.h" 14*81ad8388SMartin Matuska 15*81ad8388SMartin Matuska 16*81ad8388SMartin Matuska ///////////// 17*81ad8388SMartin Matuska // Version // 18*81ad8388SMartin Matuska ///////////// 19*81ad8388SMartin Matuska 20*81ad8388SMartin Matuska extern LZMA_API(uint32_t) 21*81ad8388SMartin Matuska lzma_version_number(void) 22*81ad8388SMartin Matuska { 23*81ad8388SMartin Matuska return LZMA_VERSION; 24*81ad8388SMartin Matuska } 25*81ad8388SMartin Matuska 26*81ad8388SMartin Matuska 27*81ad8388SMartin Matuska extern LZMA_API(const char *) 28*81ad8388SMartin Matuska lzma_version_string(void) 29*81ad8388SMartin Matuska { 30*81ad8388SMartin Matuska return LZMA_VERSION_STRING; 31*81ad8388SMartin Matuska } 32*81ad8388SMartin Matuska 33*81ad8388SMartin Matuska 34*81ad8388SMartin Matuska /////////////////////// 35*81ad8388SMartin Matuska // Memory allocation // 36*81ad8388SMartin Matuska /////////////////////// 37*81ad8388SMartin Matuska 38*81ad8388SMartin Matuska extern void * lzma_attribute((malloc)) 39*81ad8388SMartin Matuska lzma_alloc(size_t size, lzma_allocator *allocator) 40*81ad8388SMartin Matuska { 41*81ad8388SMartin Matuska // Some malloc() variants return NULL if called with size == 0. 42*81ad8388SMartin Matuska if (size == 0) 43*81ad8388SMartin Matuska size = 1; 44*81ad8388SMartin Matuska 45*81ad8388SMartin Matuska void *ptr; 46*81ad8388SMartin Matuska 47*81ad8388SMartin Matuska if (allocator != NULL && allocator->alloc != NULL) 48*81ad8388SMartin Matuska ptr = allocator->alloc(allocator->opaque, 1, size); 49*81ad8388SMartin Matuska else 50*81ad8388SMartin Matuska ptr = malloc(size); 51*81ad8388SMartin Matuska 52*81ad8388SMartin Matuska return ptr; 53*81ad8388SMartin Matuska } 54*81ad8388SMartin Matuska 55*81ad8388SMartin Matuska 56*81ad8388SMartin Matuska extern void 57*81ad8388SMartin Matuska lzma_free(void *ptr, lzma_allocator *allocator) 58*81ad8388SMartin Matuska { 59*81ad8388SMartin Matuska if (allocator != NULL && allocator->free != NULL) 60*81ad8388SMartin Matuska allocator->free(allocator->opaque, ptr); 61*81ad8388SMartin Matuska else 62*81ad8388SMartin Matuska free(ptr); 63*81ad8388SMartin Matuska 64*81ad8388SMartin Matuska return; 65*81ad8388SMartin Matuska } 66*81ad8388SMartin Matuska 67*81ad8388SMartin Matuska 68*81ad8388SMartin Matuska ////////// 69*81ad8388SMartin Matuska // Misc // 70*81ad8388SMartin Matuska ////////// 71*81ad8388SMartin Matuska 72*81ad8388SMartin Matuska extern size_t 73*81ad8388SMartin Matuska lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, 74*81ad8388SMartin Matuska size_t in_size, uint8_t *restrict out, 75*81ad8388SMartin Matuska size_t *restrict out_pos, size_t out_size) 76*81ad8388SMartin Matuska { 77*81ad8388SMartin Matuska const size_t in_avail = in_size - *in_pos; 78*81ad8388SMartin Matuska const size_t out_avail = out_size - *out_pos; 79*81ad8388SMartin Matuska const size_t copy_size = MIN(in_avail, out_avail); 80*81ad8388SMartin Matuska 81*81ad8388SMartin Matuska memcpy(out + *out_pos, in + *in_pos, copy_size); 82*81ad8388SMartin Matuska 83*81ad8388SMartin Matuska *in_pos += copy_size; 84*81ad8388SMartin Matuska *out_pos += copy_size; 85*81ad8388SMartin Matuska 86*81ad8388SMartin Matuska return copy_size; 87*81ad8388SMartin Matuska } 88*81ad8388SMartin Matuska 89*81ad8388SMartin Matuska 90*81ad8388SMartin Matuska extern lzma_ret 91*81ad8388SMartin Matuska lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator, 92*81ad8388SMartin Matuska const lzma_filter_info *filters) 93*81ad8388SMartin Matuska { 94*81ad8388SMartin Matuska lzma_next_coder_init(filters[0].init, next, allocator); 95*81ad8388SMartin Matuska next->id = filters[0].id; 96*81ad8388SMartin Matuska return filters[0].init == NULL 97*81ad8388SMartin Matuska ? LZMA_OK : filters[0].init(next, allocator, filters); 98*81ad8388SMartin Matuska } 99*81ad8388SMartin Matuska 100*81ad8388SMartin Matuska 101*81ad8388SMartin Matuska extern lzma_ret 102*81ad8388SMartin Matuska lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator, 103*81ad8388SMartin Matuska const lzma_filter *reversed_filters) 104*81ad8388SMartin Matuska { 105*81ad8388SMartin Matuska // Check that the application isn't trying to change the Filter ID. 106*81ad8388SMartin Matuska // End of filters is indicated with LZMA_VLI_UNKNOWN in both 107*81ad8388SMartin Matuska // reversed_filters[0].id and next->id. 108*81ad8388SMartin Matuska if (reversed_filters[0].id != next->id) 109*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 110*81ad8388SMartin Matuska 111*81ad8388SMartin Matuska if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) 112*81ad8388SMartin Matuska return LZMA_OK; 113*81ad8388SMartin Matuska 114*81ad8388SMartin Matuska assert(next->update != NULL); 115*81ad8388SMartin Matuska return next->update(next->coder, allocator, NULL, reversed_filters); 116*81ad8388SMartin Matuska } 117*81ad8388SMartin Matuska 118*81ad8388SMartin Matuska 119*81ad8388SMartin Matuska extern void 120*81ad8388SMartin Matuska lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator) 121*81ad8388SMartin Matuska { 122*81ad8388SMartin Matuska if (next->init != (uintptr_t)(NULL)) { 123*81ad8388SMartin Matuska // To avoid tiny end functions that simply call 124*81ad8388SMartin Matuska // lzma_free(coder, allocator), we allow leaving next->end 125*81ad8388SMartin Matuska // NULL and call lzma_free() here. 126*81ad8388SMartin Matuska if (next->end != NULL) 127*81ad8388SMartin Matuska next->end(next->coder, allocator); 128*81ad8388SMartin Matuska else 129*81ad8388SMartin Matuska lzma_free(next->coder, allocator); 130*81ad8388SMartin Matuska 131*81ad8388SMartin Matuska // Reset the variables so the we don't accidentally think 132*81ad8388SMartin Matuska // that it is an already initialized coder. 133*81ad8388SMartin Matuska *next = LZMA_NEXT_CODER_INIT; 134*81ad8388SMartin Matuska } 135*81ad8388SMartin Matuska 136*81ad8388SMartin Matuska return; 137*81ad8388SMartin Matuska } 138*81ad8388SMartin Matuska 139*81ad8388SMartin Matuska 140*81ad8388SMartin Matuska ////////////////////////////////////// 141*81ad8388SMartin Matuska // External to internal API wrapper // 142*81ad8388SMartin Matuska ////////////////////////////////////// 143*81ad8388SMartin Matuska 144*81ad8388SMartin Matuska extern lzma_ret 145*81ad8388SMartin Matuska lzma_strm_init(lzma_stream *strm) 146*81ad8388SMartin Matuska { 147*81ad8388SMartin Matuska if (strm == NULL) 148*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 149*81ad8388SMartin Matuska 150*81ad8388SMartin Matuska if (strm->internal == NULL) { 151*81ad8388SMartin Matuska strm->internal = lzma_alloc(sizeof(lzma_internal), 152*81ad8388SMartin Matuska strm->allocator); 153*81ad8388SMartin Matuska if (strm->internal == NULL) 154*81ad8388SMartin Matuska return LZMA_MEM_ERROR; 155*81ad8388SMartin Matuska 156*81ad8388SMartin Matuska strm->internal->next = LZMA_NEXT_CODER_INIT; 157*81ad8388SMartin Matuska } 158*81ad8388SMartin Matuska 159*81ad8388SMartin Matuska strm->internal->supported_actions[LZMA_RUN] = false; 160*81ad8388SMartin Matuska strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false; 161*81ad8388SMartin Matuska strm->internal->supported_actions[LZMA_FULL_FLUSH] = false; 162*81ad8388SMartin Matuska strm->internal->supported_actions[LZMA_FINISH] = false; 163*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 164*81ad8388SMartin Matuska strm->internal->allow_buf_error = false; 165*81ad8388SMartin Matuska 166*81ad8388SMartin Matuska strm->total_in = 0; 167*81ad8388SMartin Matuska strm->total_out = 0; 168*81ad8388SMartin Matuska 169*81ad8388SMartin Matuska return LZMA_OK; 170*81ad8388SMartin Matuska } 171*81ad8388SMartin Matuska 172*81ad8388SMartin Matuska 173*81ad8388SMartin Matuska extern LZMA_API(lzma_ret) 174*81ad8388SMartin Matuska lzma_code(lzma_stream *strm, lzma_action action) 175*81ad8388SMartin Matuska { 176*81ad8388SMartin Matuska // Sanity checks 177*81ad8388SMartin Matuska if ((strm->next_in == NULL && strm->avail_in != 0) 178*81ad8388SMartin Matuska || (strm->next_out == NULL && strm->avail_out != 0) 179*81ad8388SMartin Matuska || strm->internal == NULL 180*81ad8388SMartin Matuska || strm->internal->next.code == NULL 181*81ad8388SMartin Matuska || (unsigned int)(action) > LZMA_FINISH 182*81ad8388SMartin Matuska || !strm->internal->supported_actions[action]) 183*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 184*81ad8388SMartin Matuska 185*81ad8388SMartin Matuska switch (strm->internal->sequence) { 186*81ad8388SMartin Matuska case ISEQ_RUN: 187*81ad8388SMartin Matuska switch (action) { 188*81ad8388SMartin Matuska case LZMA_RUN: 189*81ad8388SMartin Matuska break; 190*81ad8388SMartin Matuska 191*81ad8388SMartin Matuska case LZMA_SYNC_FLUSH: 192*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_SYNC_FLUSH; 193*81ad8388SMartin Matuska break; 194*81ad8388SMartin Matuska 195*81ad8388SMartin Matuska case LZMA_FULL_FLUSH: 196*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_FULL_FLUSH; 197*81ad8388SMartin Matuska break; 198*81ad8388SMartin Matuska 199*81ad8388SMartin Matuska case LZMA_FINISH: 200*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_FINISH; 201*81ad8388SMartin Matuska break; 202*81ad8388SMartin Matuska } 203*81ad8388SMartin Matuska 204*81ad8388SMartin Matuska break; 205*81ad8388SMartin Matuska 206*81ad8388SMartin Matuska case ISEQ_SYNC_FLUSH: 207*81ad8388SMartin Matuska // The same action must be used until we return 208*81ad8388SMartin Matuska // LZMA_STREAM_END, and the amount of input must not change. 209*81ad8388SMartin Matuska if (action != LZMA_SYNC_FLUSH 210*81ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 211*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 212*81ad8388SMartin Matuska 213*81ad8388SMartin Matuska break; 214*81ad8388SMartin Matuska 215*81ad8388SMartin Matuska case ISEQ_FULL_FLUSH: 216*81ad8388SMartin Matuska if (action != LZMA_FULL_FLUSH 217*81ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 218*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 219*81ad8388SMartin Matuska 220*81ad8388SMartin Matuska break; 221*81ad8388SMartin Matuska 222*81ad8388SMartin Matuska case ISEQ_FINISH: 223*81ad8388SMartin Matuska if (action != LZMA_FINISH 224*81ad8388SMartin Matuska || strm->internal->avail_in != strm->avail_in) 225*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 226*81ad8388SMartin Matuska 227*81ad8388SMartin Matuska break; 228*81ad8388SMartin Matuska 229*81ad8388SMartin Matuska case ISEQ_END: 230*81ad8388SMartin Matuska return LZMA_STREAM_END; 231*81ad8388SMartin Matuska 232*81ad8388SMartin Matuska case ISEQ_ERROR: 233*81ad8388SMartin Matuska default: 234*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 235*81ad8388SMartin Matuska } 236*81ad8388SMartin Matuska 237*81ad8388SMartin Matuska size_t in_pos = 0; 238*81ad8388SMartin Matuska size_t out_pos = 0; 239*81ad8388SMartin Matuska lzma_ret ret = strm->internal->next.code( 240*81ad8388SMartin Matuska strm->internal->next.coder, strm->allocator, 241*81ad8388SMartin Matuska strm->next_in, &in_pos, strm->avail_in, 242*81ad8388SMartin Matuska strm->next_out, &out_pos, strm->avail_out, action); 243*81ad8388SMartin Matuska 244*81ad8388SMartin Matuska strm->next_in += in_pos; 245*81ad8388SMartin Matuska strm->avail_in -= in_pos; 246*81ad8388SMartin Matuska strm->total_in += in_pos; 247*81ad8388SMartin Matuska 248*81ad8388SMartin Matuska strm->next_out += out_pos; 249*81ad8388SMartin Matuska strm->avail_out -= out_pos; 250*81ad8388SMartin Matuska strm->total_out += out_pos; 251*81ad8388SMartin Matuska 252*81ad8388SMartin Matuska strm->internal->avail_in = strm->avail_in; 253*81ad8388SMartin Matuska 254*81ad8388SMartin Matuska switch (ret) { 255*81ad8388SMartin Matuska case LZMA_OK: 256*81ad8388SMartin Matuska // Don't return LZMA_BUF_ERROR when it happens the first time. 257*81ad8388SMartin Matuska // This is to avoid returning LZMA_BUF_ERROR when avail_out 258*81ad8388SMartin Matuska // was zero but still there was no more data left to written 259*81ad8388SMartin Matuska // to next_out. 260*81ad8388SMartin Matuska if (out_pos == 0 && in_pos == 0) { 261*81ad8388SMartin Matuska if (strm->internal->allow_buf_error) 262*81ad8388SMartin Matuska ret = LZMA_BUF_ERROR; 263*81ad8388SMartin Matuska else 264*81ad8388SMartin Matuska strm->internal->allow_buf_error = true; 265*81ad8388SMartin Matuska } else { 266*81ad8388SMartin Matuska strm->internal->allow_buf_error = false; 267*81ad8388SMartin Matuska } 268*81ad8388SMartin Matuska break; 269*81ad8388SMartin Matuska 270*81ad8388SMartin Matuska case LZMA_STREAM_END: 271*81ad8388SMartin Matuska if (strm->internal->sequence == ISEQ_SYNC_FLUSH 272*81ad8388SMartin Matuska || strm->internal->sequence == ISEQ_FULL_FLUSH) 273*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_RUN; 274*81ad8388SMartin Matuska else 275*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_END; 276*81ad8388SMartin Matuska 277*81ad8388SMartin Matuska // Fall through 278*81ad8388SMartin Matuska 279*81ad8388SMartin Matuska case LZMA_NO_CHECK: 280*81ad8388SMartin Matuska case LZMA_UNSUPPORTED_CHECK: 281*81ad8388SMartin Matuska case LZMA_GET_CHECK: 282*81ad8388SMartin Matuska case LZMA_MEMLIMIT_ERROR: 283*81ad8388SMartin Matuska // Something else than LZMA_OK, but not a fatal error, 284*81ad8388SMartin Matuska // that is, coding may be continued (except if ISEQ_END). 285*81ad8388SMartin Matuska strm->internal->allow_buf_error = false; 286*81ad8388SMartin Matuska break; 287*81ad8388SMartin Matuska 288*81ad8388SMartin Matuska default: 289*81ad8388SMartin Matuska // All the other errors are fatal; coding cannot be continued. 290*81ad8388SMartin Matuska assert(ret != LZMA_BUF_ERROR); 291*81ad8388SMartin Matuska strm->internal->sequence = ISEQ_ERROR; 292*81ad8388SMartin Matuska break; 293*81ad8388SMartin Matuska } 294*81ad8388SMartin Matuska 295*81ad8388SMartin Matuska return ret; 296*81ad8388SMartin Matuska } 297*81ad8388SMartin Matuska 298*81ad8388SMartin Matuska 299*81ad8388SMartin Matuska extern LZMA_API(void) 300*81ad8388SMartin Matuska lzma_end(lzma_stream *strm) 301*81ad8388SMartin Matuska { 302*81ad8388SMartin Matuska if (strm != NULL && strm->internal != NULL) { 303*81ad8388SMartin Matuska lzma_next_end(&strm->internal->next, strm->allocator); 304*81ad8388SMartin Matuska lzma_free(strm->internal, strm->allocator); 305*81ad8388SMartin Matuska strm->internal = NULL; 306*81ad8388SMartin Matuska } 307*81ad8388SMartin Matuska 308*81ad8388SMartin Matuska return; 309*81ad8388SMartin Matuska } 310*81ad8388SMartin Matuska 311*81ad8388SMartin Matuska 312*81ad8388SMartin Matuska extern LZMA_API(lzma_check) 313*81ad8388SMartin Matuska lzma_get_check(const lzma_stream *strm) 314*81ad8388SMartin Matuska { 315*81ad8388SMartin Matuska // Return LZMA_CHECK_NONE if we cannot know the check type. 316*81ad8388SMartin Matuska // It's a bug in the application if this happens. 317*81ad8388SMartin Matuska if (strm->internal->next.get_check == NULL) 318*81ad8388SMartin Matuska return LZMA_CHECK_NONE; 319*81ad8388SMartin Matuska 320*81ad8388SMartin Matuska return strm->internal->next.get_check(strm->internal->next.coder); 321*81ad8388SMartin Matuska } 322*81ad8388SMartin Matuska 323*81ad8388SMartin Matuska 324*81ad8388SMartin Matuska extern LZMA_API(uint64_t) 325*81ad8388SMartin Matuska lzma_memusage(const lzma_stream *strm) 326*81ad8388SMartin Matuska { 327*81ad8388SMartin Matuska uint64_t memusage; 328*81ad8388SMartin Matuska uint64_t old_memlimit; 329*81ad8388SMartin Matuska 330*81ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 331*81ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 332*81ad8388SMartin Matuska || strm->internal->next.memconfig( 333*81ad8388SMartin Matuska strm->internal->next.coder, 334*81ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 335*81ad8388SMartin Matuska return 0; 336*81ad8388SMartin Matuska 337*81ad8388SMartin Matuska return memusage; 338*81ad8388SMartin Matuska } 339*81ad8388SMartin Matuska 340*81ad8388SMartin Matuska 341*81ad8388SMartin Matuska extern LZMA_API(uint64_t) 342*81ad8388SMartin Matuska lzma_memlimit_get(const lzma_stream *strm) 343*81ad8388SMartin Matuska { 344*81ad8388SMartin Matuska uint64_t old_memlimit; 345*81ad8388SMartin Matuska uint64_t memusage; 346*81ad8388SMartin Matuska 347*81ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 348*81ad8388SMartin Matuska || strm->internal->next.memconfig == NULL 349*81ad8388SMartin Matuska || strm->internal->next.memconfig( 350*81ad8388SMartin Matuska strm->internal->next.coder, 351*81ad8388SMartin Matuska &memusage, &old_memlimit, 0) != LZMA_OK) 352*81ad8388SMartin Matuska return 0; 353*81ad8388SMartin Matuska 354*81ad8388SMartin Matuska return old_memlimit; 355*81ad8388SMartin Matuska } 356*81ad8388SMartin Matuska 357*81ad8388SMartin Matuska 358*81ad8388SMartin Matuska extern LZMA_API(lzma_ret) 359*81ad8388SMartin Matuska lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) 360*81ad8388SMartin Matuska { 361*81ad8388SMartin Matuska // Dummy variables to simplify memconfig functions 362*81ad8388SMartin Matuska uint64_t old_memlimit; 363*81ad8388SMartin Matuska uint64_t memusage; 364*81ad8388SMartin Matuska 365*81ad8388SMartin Matuska if (strm == NULL || strm->internal == NULL 366*81ad8388SMartin Matuska || strm->internal->next.memconfig == NULL) 367*81ad8388SMartin Matuska return LZMA_PROG_ERROR; 368*81ad8388SMartin Matuska 369*81ad8388SMartin Matuska if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE) 370*81ad8388SMartin Matuska return LZMA_MEMLIMIT_ERROR; 371*81ad8388SMartin Matuska 372*81ad8388SMartin Matuska return strm->internal->next.memconfig(strm->internal->next.coder, 373*81ad8388SMartin Matuska &memusage, &old_memlimit, new_memlimit); 374*81ad8388SMartin Matuska } 375