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)
39207753Smmlzma_alloc(size_t size, 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
56207753Smmextern void
57207753Smmlzma_free(void *ptr, lzma_allocator *allocator)
58207753Smm{
59207753Smm	if (allocator != NULL && allocator->free != NULL)
60207753Smm		allocator->free(allocator->opaque, ptr);
61207753Smm	else
62207753Smm		free(ptr);
63207753Smm
64207753Smm	return;
65207753Smm}
66207753Smm
67207753Smm
68207753Smm//////////
69207753Smm// Misc //
70207753Smm//////////
71207753Smm
72207753Smmextern size_t
73207753Smmlzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
74207753Smm		size_t in_size, uint8_t *restrict out,
75207753Smm		size_t *restrict out_pos, size_t out_size)
76207753Smm{
77207753Smm	const size_t in_avail = in_size - *in_pos;
78207753Smm	const size_t out_avail = out_size - *out_pos;
79213700Smm	const size_t copy_size = my_min(in_avail, out_avail);
80207753Smm
81207753Smm	memcpy(out + *out_pos, in + *in_pos, copy_size);
82207753Smm
83207753Smm	*in_pos += copy_size;
84207753Smm	*out_pos += copy_size;
85207753Smm
86207753Smm	return copy_size;
87207753Smm}
88207753Smm
89207753Smm
90207753Smmextern lzma_ret
91207753Smmlzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
92207753Smm		const lzma_filter_info *filters)
93207753Smm{
94207753Smm	lzma_next_coder_init(filters[0].init, next, allocator);
95207753Smm	next->id = filters[0].id;
96207753Smm	return filters[0].init == NULL
97207753Smm			? LZMA_OK : filters[0].init(next, allocator, filters);
98207753Smm}
99207753Smm
100207753Smm
101207753Smmextern lzma_ret
102207753Smmlzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
103207753Smm		const lzma_filter *reversed_filters)
104207753Smm{
105207753Smm	// Check that the application isn't trying to change the Filter ID.
106207753Smm	// End of filters is indicated with LZMA_VLI_UNKNOWN in both
107207753Smm	// reversed_filters[0].id and next->id.
108207753Smm	if (reversed_filters[0].id != next->id)
109207753Smm		return LZMA_PROG_ERROR;
110207753Smm
111207753Smm	if (reversed_filters[0].id == LZMA_VLI_UNKNOWN)
112207753Smm		return LZMA_OK;
113207753Smm
114207753Smm	assert(next->update != NULL);
115207753Smm	return next->update(next->coder, allocator, NULL, reversed_filters);
116207753Smm}
117207753Smm
118207753Smm
119207753Smmextern void
120207753Smmlzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
121207753Smm{
122207753Smm	if (next->init != (uintptr_t)(NULL)) {
123207753Smm		// To avoid tiny end functions that simply call
124207753Smm		// lzma_free(coder, allocator), we allow leaving next->end
125207753Smm		// NULL and call lzma_free() here.
126207753Smm		if (next->end != NULL)
127207753Smm			next->end(next->coder, allocator);
128207753Smm		else
129207753Smm			lzma_free(next->coder, allocator);
130207753Smm
131207753Smm		// Reset the variables so the we don't accidentally think
132207753Smm		// that it is an already initialized coder.
133207753Smm		*next = LZMA_NEXT_CODER_INIT;
134207753Smm	}
135207753Smm
136207753Smm	return;
137207753Smm}
138207753Smm
139207753Smm
140207753Smm//////////////////////////////////////
141207753Smm// External to internal API wrapper //
142207753Smm//////////////////////////////////////
143207753Smm
144207753Smmextern lzma_ret
145207753Smmlzma_strm_init(lzma_stream *strm)
146207753Smm{
147207753Smm	if (strm == NULL)
148207753Smm		return LZMA_PROG_ERROR;
149207753Smm
150207753Smm	if (strm->internal == NULL) {
151207753Smm		strm->internal = lzma_alloc(sizeof(lzma_internal),
152207753Smm				strm->allocator);
153207753Smm		if (strm->internal == NULL)
154207753Smm			return LZMA_MEM_ERROR;
155207753Smm
156207753Smm		strm->internal->next = LZMA_NEXT_CODER_INIT;
157207753Smm	}
158207753Smm
159207753Smm	strm->internal->supported_actions[LZMA_RUN] = false;
160207753Smm	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
161207753Smm	strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
162207753Smm	strm->internal->supported_actions[LZMA_FINISH] = false;
163207753Smm	strm->internal->sequence = ISEQ_RUN;
164207753Smm	strm->internal->allow_buf_error = false;
165207753Smm
166207753Smm	strm->total_in = 0;
167207753Smm	strm->total_out = 0;
168207753Smm
169207753Smm	return LZMA_OK;
170207753Smm}
171207753Smm
172207753Smm
173207753Smmextern LZMA_API(lzma_ret)
174207753Smmlzma_code(lzma_stream *strm, lzma_action action)
175207753Smm{
176207753Smm	// Sanity checks
177207753Smm	if ((strm->next_in == NULL && strm->avail_in != 0)
178207753Smm			|| (strm->next_out == NULL && strm->avail_out != 0)
179207753Smm			|| strm->internal == NULL
180207753Smm			|| strm->internal->next.code == NULL
181207753Smm			|| (unsigned int)(action) > LZMA_FINISH
182207753Smm			|| !strm->internal->supported_actions[action])
183207753Smm		return LZMA_PROG_ERROR;
184207753Smm
185215187Smm	// Check if unsupported members have been set to non-zero or non-NULL,
186215187Smm	// which would indicate that some new feature is wanted.
187215187Smm	if (strm->reserved_ptr1 != NULL
188215187Smm			|| strm->reserved_ptr2 != NULL
189215187Smm			|| strm->reserved_ptr3 != NULL
190215187Smm			|| strm->reserved_ptr4 != NULL
191215187Smm			|| strm->reserved_int1 != 0
192215187Smm			|| strm->reserved_int2 != 0
193215187Smm			|| strm->reserved_int3 != 0
194215187Smm			|| strm->reserved_int4 != 0
195215187Smm			|| strm->reserved_enum1 != LZMA_RESERVED_ENUM
196215187Smm			|| strm->reserved_enum2 != LZMA_RESERVED_ENUM)
197215187Smm		return LZMA_OPTIONS_ERROR;
198215187Smm
199207753Smm	switch (strm->internal->sequence) {
200207753Smm	case ISEQ_RUN:
201207753Smm		switch (action) {
202207753Smm		case LZMA_RUN:
203207753Smm			break;
204207753Smm
205207753Smm		case LZMA_SYNC_FLUSH:
206207753Smm			strm->internal->sequence = ISEQ_SYNC_FLUSH;
207207753Smm			break;
208207753Smm
209207753Smm		case LZMA_FULL_FLUSH:
210207753Smm			strm->internal->sequence = ISEQ_FULL_FLUSH;
211207753Smm			break;
212207753Smm
213207753Smm		case LZMA_FINISH:
214207753Smm			strm->internal->sequence = ISEQ_FINISH;
215207753Smm			break;
216207753Smm		}
217207753Smm
218207753Smm		break;
219207753Smm
220207753Smm	case ISEQ_SYNC_FLUSH:
221207753Smm		// The same action must be used until we return
222207753Smm		// LZMA_STREAM_END, and the amount of input must not change.
223207753Smm		if (action != LZMA_SYNC_FLUSH
224207753Smm				|| strm->internal->avail_in != strm->avail_in)
225207753Smm			return LZMA_PROG_ERROR;
226207753Smm
227207753Smm		break;
228207753Smm
229207753Smm	case ISEQ_FULL_FLUSH:
230207753Smm		if (action != LZMA_FULL_FLUSH
231207753Smm				|| strm->internal->avail_in != strm->avail_in)
232207753Smm			return LZMA_PROG_ERROR;
233207753Smm
234207753Smm		break;
235207753Smm
236207753Smm	case ISEQ_FINISH:
237207753Smm		if (action != LZMA_FINISH
238207753Smm				|| strm->internal->avail_in != strm->avail_in)
239207753Smm			return LZMA_PROG_ERROR;
240207753Smm
241207753Smm		break;
242207753Smm
243207753Smm	case ISEQ_END:
244207753Smm		return LZMA_STREAM_END;
245207753Smm
246207753Smm	case ISEQ_ERROR:
247207753Smm	default:
248207753Smm		return LZMA_PROG_ERROR;
249207753Smm	}
250207753Smm
251207753Smm	size_t in_pos = 0;
252207753Smm	size_t out_pos = 0;
253207753Smm	lzma_ret ret = strm->internal->next.code(
254207753Smm			strm->internal->next.coder, strm->allocator,
255207753Smm			strm->next_in, &in_pos, strm->avail_in,
256207753Smm			strm->next_out, &out_pos, strm->avail_out, action);
257207753Smm
258207753Smm	strm->next_in += in_pos;
259207753Smm	strm->avail_in -= in_pos;
260207753Smm	strm->total_in += in_pos;
261207753Smm
262207753Smm	strm->next_out += out_pos;
263207753Smm	strm->avail_out -= out_pos;
264207753Smm	strm->total_out += out_pos;
265207753Smm
266207753Smm	strm->internal->avail_in = strm->avail_in;
267207753Smm
268207753Smm	switch (ret) {
269207753Smm	case LZMA_OK:
270207753Smm		// Don't return LZMA_BUF_ERROR when it happens the first time.
271207753Smm		// This is to avoid returning LZMA_BUF_ERROR when avail_out
272207753Smm		// was zero but still there was no more data left to written
273207753Smm		// to next_out.
274207753Smm		if (out_pos == 0 && in_pos == 0) {
275207753Smm			if (strm->internal->allow_buf_error)
276207753Smm				ret = LZMA_BUF_ERROR;
277207753Smm			else
278207753Smm				strm->internal->allow_buf_error = true;
279207753Smm		} else {
280207753Smm			strm->internal->allow_buf_error = false;
281207753Smm		}
282207753Smm		break;
283207753Smm
284207753Smm	case LZMA_STREAM_END:
285207753Smm		if (strm->internal->sequence == ISEQ_SYNC_FLUSH
286207753Smm				|| strm->internal->sequence == ISEQ_FULL_FLUSH)
287207753Smm			strm->internal->sequence = ISEQ_RUN;
288207753Smm		else
289207753Smm			strm->internal->sequence = ISEQ_END;
290207753Smm
291207753Smm	// Fall through
292207753Smm
293207753Smm	case LZMA_NO_CHECK:
294207753Smm	case LZMA_UNSUPPORTED_CHECK:
295207753Smm	case LZMA_GET_CHECK:
296207753Smm	case LZMA_MEMLIMIT_ERROR:
297207753Smm		// Something else than LZMA_OK, but not a fatal error,
298207753Smm		// that is, coding may be continued (except if ISEQ_END).
299207753Smm		strm->internal->allow_buf_error = false;
300207753Smm		break;
301207753Smm
302207753Smm	default:
303207753Smm		// All the other errors are fatal; coding cannot be continued.
304207753Smm		assert(ret != LZMA_BUF_ERROR);
305207753Smm		strm->internal->sequence = ISEQ_ERROR;
306207753Smm		break;
307207753Smm	}
308207753Smm
309207753Smm	return ret;
310207753Smm}
311207753Smm
312207753Smm
313207753Smmextern LZMA_API(void)
314207753Smmlzma_end(lzma_stream *strm)
315207753Smm{
316207753Smm	if (strm != NULL && strm->internal != NULL) {
317207753Smm		lzma_next_end(&strm->internal->next, strm->allocator);
318207753Smm		lzma_free(strm->internal, strm->allocator);
319207753Smm		strm->internal = NULL;
320207753Smm	}
321207753Smm
322207753Smm	return;
323207753Smm}
324207753Smm
325207753Smm
326207753Smmextern LZMA_API(lzma_check)
327207753Smmlzma_get_check(const lzma_stream *strm)
328207753Smm{
329207753Smm	// Return LZMA_CHECK_NONE if we cannot know the check type.
330207753Smm	// It's a bug in the application if this happens.
331207753Smm	if (strm->internal->next.get_check == NULL)
332207753Smm		return LZMA_CHECK_NONE;
333207753Smm
334207753Smm	return strm->internal->next.get_check(strm->internal->next.coder);
335207753Smm}
336207753Smm
337207753Smm
338207753Smmextern LZMA_API(uint64_t)
339207753Smmlzma_memusage(const lzma_stream *strm)
340207753Smm{
341207753Smm	uint64_t memusage;
342207753Smm	uint64_t old_memlimit;
343207753Smm
344207753Smm	if (strm == NULL || strm->internal == NULL
345207753Smm			|| strm->internal->next.memconfig == NULL
346207753Smm			|| strm->internal->next.memconfig(
347207753Smm				strm->internal->next.coder,
348207753Smm				&memusage, &old_memlimit, 0) != LZMA_OK)
349207753Smm		return 0;
350207753Smm
351207753Smm	return memusage;
352207753Smm}
353207753Smm
354207753Smm
355207753Smmextern LZMA_API(uint64_t)
356207753Smmlzma_memlimit_get(const lzma_stream *strm)
357207753Smm{
358207753Smm	uint64_t old_memlimit;
359207753Smm	uint64_t memusage;
360207753Smm
361207753Smm	if (strm == NULL || strm->internal == NULL
362207753Smm			|| strm->internal->next.memconfig == NULL
363207753Smm			|| strm->internal->next.memconfig(
364207753Smm				strm->internal->next.coder,
365207753Smm				&memusage, &old_memlimit, 0) != LZMA_OK)
366207753Smm		return 0;
367207753Smm
368207753Smm	return old_memlimit;
369207753Smm}
370207753Smm
371207753Smm
372207753Smmextern LZMA_API(lzma_ret)
373207753Smmlzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
374207753Smm{
375207753Smm	// Dummy variables to simplify memconfig functions
376207753Smm	uint64_t old_memlimit;
377207753Smm	uint64_t memusage;
378207753Smm
379207753Smm	if (strm == NULL || strm->internal == NULL
380207753Smm			|| strm->internal->next.memconfig == NULL)
381207753Smm		return LZMA_PROG_ERROR;
382207753Smm
383207753Smm	if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
384207753Smm		return LZMA_MEMLIMIT_ERROR;
385207753Smm
386207753Smm	return strm->internal->next.memconfig(strm->internal->next.coder,
387207753Smm			&memusage, &old_memlimit, new_memlimit);
388207753Smm}
389