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)
39292588Sdelphijlzma_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
56292588Sdelphijextern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
57292588Sdelphijlzma_alloc_zero(size_t size, const lzma_allocator *allocator)
58292588Sdelphij{
59292588Sdelphij	// Some calloc() variants return NULL if called with size == 0.
60292588Sdelphij	if (size == 0)
61292588Sdelphij		size = 1;
62292588Sdelphij
63292588Sdelphij	void *ptr;
64292588Sdelphij
65292588Sdelphij	if (allocator != NULL && allocator->alloc != NULL) {
66292588Sdelphij		ptr = allocator->alloc(allocator->opaque, 1, size);
67292588Sdelphij		if (ptr != NULL)
68292588Sdelphij			memzero(ptr, size);
69292588Sdelphij	} else {
70292588Sdelphij		ptr = calloc(1, size);
71292588Sdelphij	}
72292588Sdelphij
73292588Sdelphij	return ptr;
74292588Sdelphij}
75292588Sdelphij
76292588Sdelphij
77207753Smmextern void
78292588Sdelphijlzma_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
102207753Smm	memcpy(out + *out_pos, in + *in_pos, copy_size);
103207753Smm
104207753Smm	*in_pos += copy_size;
105207753Smm	*out_pos += copy_size;
106207753Smm
107207753Smm	return copy_size;
108207753Smm}
109207753Smm
110207753Smm
111207753Smmextern lzma_ret
112292588Sdelphijlzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator,
113207753Smm		const lzma_filter_info *filters)
114207753Smm{
115207753Smm	lzma_next_coder_init(filters[0].init, next, allocator);
116207753Smm	next->id = filters[0].id;
117207753Smm	return filters[0].init == NULL
118207753Smm			? LZMA_OK : filters[0].init(next, allocator, filters);
119207753Smm}
120207753Smm
121207753Smm
122207753Smmextern lzma_ret
123292588Sdelphijlzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator,
124207753Smm		const lzma_filter *reversed_filters)
125207753Smm{
126207753Smm	// Check that the application isn't trying to change the Filter ID.
127207753Smm	// End of filters is indicated with LZMA_VLI_UNKNOWN in both
128207753Smm	// reversed_filters[0].id and next->id.
129207753Smm	if (reversed_filters[0].id != next->id)
130207753Smm		return LZMA_PROG_ERROR;
131207753Smm
132207753Smm	if (reversed_filters[0].id == LZMA_VLI_UNKNOWN)
133207753Smm		return LZMA_OK;
134207753Smm
135207753Smm	assert(next->update != NULL);
136207753Smm	return next->update(next->coder, allocator, NULL, reversed_filters);
137207753Smm}
138207753Smm
139207753Smm
140207753Smmextern void
141292588Sdelphijlzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
142207753Smm{
143207753Smm	if (next->init != (uintptr_t)(NULL)) {
144207753Smm		// To avoid tiny end functions that simply call
145207753Smm		// lzma_free(coder, allocator), we allow leaving next->end
146207753Smm		// NULL and call lzma_free() here.
147207753Smm		if (next->end != NULL)
148207753Smm			next->end(next->coder, allocator);
149207753Smm		else
150207753Smm			lzma_free(next->coder, allocator);
151207753Smm
152207753Smm		// Reset the variables so the we don't accidentally think
153207753Smm		// that it is an already initialized coder.
154207753Smm		*next = LZMA_NEXT_CODER_INIT;
155207753Smm	}
156207753Smm
157207753Smm	return;
158207753Smm}
159207753Smm
160207753Smm
161207753Smm//////////////////////////////////////
162207753Smm// External to internal API wrapper //
163207753Smm//////////////////////////////////////
164207753Smm
165207753Smmextern lzma_ret
166207753Smmlzma_strm_init(lzma_stream *strm)
167207753Smm{
168207753Smm	if (strm == NULL)
169207753Smm		return LZMA_PROG_ERROR;
170207753Smm
171207753Smm	if (strm->internal == NULL) {
172207753Smm		strm->internal = lzma_alloc(sizeof(lzma_internal),
173207753Smm				strm->allocator);
174207753Smm		if (strm->internal == NULL)
175207753Smm			return LZMA_MEM_ERROR;
176207753Smm
177207753Smm		strm->internal->next = LZMA_NEXT_CODER_INIT;
178207753Smm	}
179207753Smm
180292588Sdelphij	memzero(strm->internal->supported_actions,
181292588Sdelphij			sizeof(strm->internal->supported_actions));
182207753Smm	strm->internal->sequence = ISEQ_RUN;
183207753Smm	strm->internal->allow_buf_error = false;
184207753Smm
185207753Smm	strm->total_in = 0;
186207753Smm	strm->total_out = 0;
187207753Smm
188207753Smm	return LZMA_OK;
189207753Smm}
190207753Smm
191207753Smm
192207753Smmextern LZMA_API(lzma_ret)
193207753Smmlzma_code(lzma_stream *strm, lzma_action action)
194207753Smm{
195207753Smm	// Sanity checks
196207753Smm	if ((strm->next_in == NULL && strm->avail_in != 0)
197207753Smm			|| (strm->next_out == NULL && strm->avail_out != 0)
198207753Smm			|| strm->internal == NULL
199207753Smm			|| strm->internal->next.code == NULL
200292588Sdelphij			|| (unsigned int)(action) > LZMA_ACTION_MAX
201207753Smm			|| !strm->internal->supported_actions[action])
202207753Smm		return LZMA_PROG_ERROR;
203207753Smm
204215187Smm	// Check if unsupported members have been set to non-zero or non-NULL,
205215187Smm	// which would indicate that some new feature is wanted.
206215187Smm	if (strm->reserved_ptr1 != NULL
207215187Smm			|| strm->reserved_ptr2 != NULL
208215187Smm			|| strm->reserved_ptr3 != NULL
209215187Smm			|| strm->reserved_ptr4 != NULL
210215187Smm			|| strm->reserved_int1 != 0
211215187Smm			|| strm->reserved_int2 != 0
212215187Smm			|| strm->reserved_int3 != 0
213215187Smm			|| strm->reserved_int4 != 0
214215187Smm			|| strm->reserved_enum1 != LZMA_RESERVED_ENUM
215215187Smm			|| strm->reserved_enum2 != LZMA_RESERVED_ENUM)
216215187Smm		return LZMA_OPTIONS_ERROR;
217215187Smm
218207753Smm	switch (strm->internal->sequence) {
219207753Smm	case ISEQ_RUN:
220207753Smm		switch (action) {
221207753Smm		case LZMA_RUN:
222207753Smm			break;
223207753Smm
224207753Smm		case LZMA_SYNC_FLUSH:
225207753Smm			strm->internal->sequence = ISEQ_SYNC_FLUSH;
226207753Smm			break;
227207753Smm
228207753Smm		case LZMA_FULL_FLUSH:
229207753Smm			strm->internal->sequence = ISEQ_FULL_FLUSH;
230207753Smm			break;
231207753Smm
232207753Smm		case LZMA_FINISH:
233207753Smm			strm->internal->sequence = ISEQ_FINISH;
234207753Smm			break;
235292588Sdelphij
236292588Sdelphij		case LZMA_FULL_BARRIER:
237292588Sdelphij			strm->internal->sequence = ISEQ_FULL_BARRIER;
238292588Sdelphij			break;
239207753Smm		}
240207753Smm
241207753Smm		break;
242207753Smm
243207753Smm	case ISEQ_SYNC_FLUSH:
244207753Smm		// The same action must be used until we return
245207753Smm		// LZMA_STREAM_END, and the amount of input must not change.
246207753Smm		if (action != LZMA_SYNC_FLUSH
247207753Smm				|| strm->internal->avail_in != strm->avail_in)
248207753Smm			return LZMA_PROG_ERROR;
249207753Smm
250207753Smm		break;
251207753Smm
252207753Smm	case ISEQ_FULL_FLUSH:
253207753Smm		if (action != LZMA_FULL_FLUSH
254207753Smm				|| strm->internal->avail_in != strm->avail_in)
255207753Smm			return LZMA_PROG_ERROR;
256207753Smm
257207753Smm		break;
258207753Smm
259207753Smm	case ISEQ_FINISH:
260207753Smm		if (action != LZMA_FINISH
261207753Smm				|| strm->internal->avail_in != strm->avail_in)
262207753Smm			return LZMA_PROG_ERROR;
263207753Smm
264207753Smm		break;
265207753Smm
266292588Sdelphij	case ISEQ_FULL_BARRIER:
267292588Sdelphij		if (action != LZMA_FULL_BARRIER
268292588Sdelphij				|| strm->internal->avail_in != strm->avail_in)
269292588Sdelphij			return LZMA_PROG_ERROR;
270292588Sdelphij
271292588Sdelphij		break;
272292588Sdelphij
273207753Smm	case ISEQ_END:
274207753Smm		return LZMA_STREAM_END;
275207753Smm
276207753Smm	case ISEQ_ERROR:
277207753Smm	default:
278207753Smm		return LZMA_PROG_ERROR;
279207753Smm	}
280207753Smm
281207753Smm	size_t in_pos = 0;
282207753Smm	size_t out_pos = 0;
283207753Smm	lzma_ret ret = strm->internal->next.code(
284207753Smm			strm->internal->next.coder, strm->allocator,
285207753Smm			strm->next_in, &in_pos, strm->avail_in,
286207753Smm			strm->next_out, &out_pos, strm->avail_out, action);
287207753Smm
288207753Smm	strm->next_in += in_pos;
289207753Smm	strm->avail_in -= in_pos;
290207753Smm	strm->total_in += in_pos;
291207753Smm
292207753Smm	strm->next_out += out_pos;
293207753Smm	strm->avail_out -= out_pos;
294207753Smm	strm->total_out += out_pos;
295207753Smm
296207753Smm	strm->internal->avail_in = strm->avail_in;
297207753Smm
298292588Sdelphij	// Cast is needed to silence a warning about LZMA_TIMED_OUT, which
299292588Sdelphij	// isn't part of lzma_ret enumeration.
300292588Sdelphij	switch ((unsigned int)(ret)) {
301207753Smm	case LZMA_OK:
302207753Smm		// Don't return LZMA_BUF_ERROR when it happens the first time.
303207753Smm		// This is to avoid returning LZMA_BUF_ERROR when avail_out
304207753Smm		// was zero but still there was no more data left to written
305207753Smm		// to next_out.
306207753Smm		if (out_pos == 0 && in_pos == 0) {
307207753Smm			if (strm->internal->allow_buf_error)
308207753Smm				ret = LZMA_BUF_ERROR;
309207753Smm			else
310207753Smm				strm->internal->allow_buf_error = true;
311207753Smm		} else {
312207753Smm			strm->internal->allow_buf_error = false;
313207753Smm		}
314207753Smm		break;
315207753Smm
316292588Sdelphij	case LZMA_TIMED_OUT:
317292588Sdelphij		strm->internal->allow_buf_error = false;
318292588Sdelphij		ret = LZMA_OK;
319292588Sdelphij		break;
320292588Sdelphij
321207753Smm	case LZMA_STREAM_END:
322207753Smm		if (strm->internal->sequence == ISEQ_SYNC_FLUSH
323292588Sdelphij				|| strm->internal->sequence == ISEQ_FULL_FLUSH
324292588Sdelphij				|| strm->internal->sequence
325292588Sdelphij					== ISEQ_FULL_BARRIER)
326207753Smm			strm->internal->sequence = ISEQ_RUN;
327207753Smm		else
328207753Smm			strm->internal->sequence = ISEQ_END;
329207753Smm
330207753Smm	// Fall through
331207753Smm
332207753Smm	case LZMA_NO_CHECK:
333207753Smm	case LZMA_UNSUPPORTED_CHECK:
334207753Smm	case LZMA_GET_CHECK:
335207753Smm	case LZMA_MEMLIMIT_ERROR:
336207753Smm		// Something else than LZMA_OK, but not a fatal error,
337207753Smm		// that is, coding may be continued (except if ISEQ_END).
338207753Smm		strm->internal->allow_buf_error = false;
339207753Smm		break;
340207753Smm
341207753Smm	default:
342207753Smm		// All the other errors are fatal; coding cannot be continued.
343207753Smm		assert(ret != LZMA_BUF_ERROR);
344207753Smm		strm->internal->sequence = ISEQ_ERROR;
345207753Smm		break;
346207753Smm	}
347207753Smm
348207753Smm	return ret;
349207753Smm}
350207753Smm
351207753Smm
352207753Smmextern LZMA_API(void)
353207753Smmlzma_end(lzma_stream *strm)
354207753Smm{
355207753Smm	if (strm != NULL && strm->internal != NULL) {
356207753Smm		lzma_next_end(&strm->internal->next, strm->allocator);
357207753Smm		lzma_free(strm->internal, strm->allocator);
358207753Smm		strm->internal = NULL;
359207753Smm	}
360207753Smm
361207753Smm	return;
362207753Smm}
363207753Smm
364207753Smm
365292588Sdelphijextern LZMA_API(void)
366292588Sdelphijlzma_get_progress(lzma_stream *strm,
367292588Sdelphij		uint64_t *progress_in, uint64_t *progress_out)
368292588Sdelphij{
369292588Sdelphij	if (strm->internal->next.get_progress != NULL) {
370292588Sdelphij		strm->internal->next.get_progress(strm->internal->next.coder,
371292588Sdelphij				progress_in, progress_out);
372292588Sdelphij	} else {
373292588Sdelphij		*progress_in = strm->total_in;
374292588Sdelphij		*progress_out = strm->total_out;
375292588Sdelphij	}
376292588Sdelphij
377292588Sdelphij	return;
378292588Sdelphij}
379292588Sdelphij
380292588Sdelphij
381207753Smmextern LZMA_API(lzma_check)
382207753Smmlzma_get_check(const lzma_stream *strm)
383207753Smm{
384207753Smm	// Return LZMA_CHECK_NONE if we cannot know the check type.
385207753Smm	// It's a bug in the application if this happens.
386207753Smm	if (strm->internal->next.get_check == NULL)
387207753Smm		return LZMA_CHECK_NONE;
388207753Smm
389207753Smm	return strm->internal->next.get_check(strm->internal->next.coder);
390207753Smm}
391207753Smm
392207753Smm
393207753Smmextern LZMA_API(uint64_t)
394207753Smmlzma_memusage(const lzma_stream *strm)
395207753Smm{
396207753Smm	uint64_t memusage;
397207753Smm	uint64_t old_memlimit;
398207753Smm
399207753Smm	if (strm == NULL || strm->internal == NULL
400207753Smm			|| strm->internal->next.memconfig == NULL
401207753Smm			|| strm->internal->next.memconfig(
402207753Smm				strm->internal->next.coder,
403207753Smm				&memusage, &old_memlimit, 0) != LZMA_OK)
404207753Smm		return 0;
405207753Smm
406207753Smm	return memusage;
407207753Smm}
408207753Smm
409207753Smm
410207753Smmextern LZMA_API(uint64_t)
411207753Smmlzma_memlimit_get(const lzma_stream *strm)
412207753Smm{
413207753Smm	uint64_t old_memlimit;
414207753Smm	uint64_t memusage;
415207753Smm
416207753Smm	if (strm == NULL || strm->internal == NULL
417207753Smm			|| strm->internal->next.memconfig == NULL
418207753Smm			|| strm->internal->next.memconfig(
419207753Smm				strm->internal->next.coder,
420207753Smm				&memusage, &old_memlimit, 0) != LZMA_OK)
421207753Smm		return 0;
422207753Smm
423207753Smm	return old_memlimit;
424207753Smm}
425207753Smm
426207753Smm
427207753Smmextern LZMA_API(lzma_ret)
428207753Smmlzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
429207753Smm{
430207753Smm	// Dummy variables to simplify memconfig functions
431207753Smm	uint64_t old_memlimit;
432207753Smm	uint64_t memusage;
433207753Smm
434207753Smm	if (strm == NULL || strm->internal == NULL
435207753Smm			|| strm->internal->next.memconfig == NULL)
436207753Smm		return LZMA_PROG_ERROR;
437207753Smm
438207753Smm	if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
439207753Smm		return LZMA_MEMLIMIT_ERROR;
440207753Smm
441207753Smm	return strm->internal->next.memconfig(strm->internal->next.coder,
442207753Smm			&memusage, &old_memlimit, new_memlimit);
443207753Smm}
444