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