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