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