brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · af9a976 Raw
123 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <errno.h>3#include <lzma.h>4#include <stdio.h>5#include <linux/compiler.h>6#include <sys/types.h>7#include <sys/stat.h>8#include <fcntl.h>9#include "compress.h"10#include "debug.h"11#include <string.h>12#include <unistd.h>13#include <internal/lib.h>14 15#define BUFSIZE 819216 17static const char *lzma_strerror(lzma_ret ret)18{19	switch ((int) ret) {20	case LZMA_MEM_ERROR:21		return "Memory allocation failed";22	case LZMA_OPTIONS_ERROR:23		return "Unsupported decompressor flags";24	case LZMA_FORMAT_ERROR:25		return "The input is not in the .xz format";26	case LZMA_DATA_ERROR:27		return "Compressed file is corrupt";28	case LZMA_BUF_ERROR:29		return "Compressed file is truncated or otherwise corrupt";30	default:31		return "Unknown error, possibly a bug";32	}33}34 35int lzma_decompress_to_file(const char *input, int output_fd)36{37	lzma_action action = LZMA_RUN;38	lzma_stream strm   = LZMA_STREAM_INIT;39	lzma_ret ret;40	int err = -1;41 42	u8 buf_in[BUFSIZE];43	u8 buf_out[BUFSIZE];44	FILE *infile;45 46	infile = fopen(input, "rb");47	if (!infile) {48		pr_debug("lzma: fopen failed on %s: '%s'\n", input, strerror(errno));49		return -1;50	}51 52	ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);53	if (ret != LZMA_OK) {54		pr_debug("lzma: lzma_stream_decoder failed %s (%d)\n", lzma_strerror(ret), ret);55		goto err_fclose;56	}57 58	strm.next_in   = NULL;59	strm.avail_in  = 0;60	strm.next_out  = buf_out;61	strm.avail_out = sizeof(buf_out);62 63	while (1) {64		if (strm.avail_in == 0 && !feof(infile)) {65			strm.next_in  = buf_in;66			strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile);67 68			if (ferror(infile)) {69				pr_debug("lzma: read error: %s\n", strerror(errno));70				goto err_lzma_end;71			}72 73			if (feof(infile))74				action = LZMA_FINISH;75		}76 77		ret = lzma_code(&strm, action);78 79		if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {80			ssize_t write_size = sizeof(buf_out) - strm.avail_out;81 82			if (writen(output_fd, buf_out, write_size) != write_size) {83				pr_debug("lzma: write error: %s\n", strerror(errno));84				goto err_lzma_end;85			}86 87			strm.next_out  = buf_out;88			strm.avail_out = sizeof(buf_out);89		}90 91		if (ret != LZMA_OK) {92			if (ret == LZMA_STREAM_END)93				break;94 95			pr_debug("lzma: failed %s\n", lzma_strerror(ret));96			goto err_lzma_end;97		}98	}99 100	err = 0;101err_lzma_end:102	lzma_end(&strm);103err_fclose:104	fclose(infile);105	return err;106}107 108bool lzma_is_compressed(const char *input)109{110	int fd = open(input, O_RDONLY);111	const uint8_t magic[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };112	char buf[6] = { 0 };113	ssize_t rc;114 115	if (fd < 0)116		return -1;117 118	rc = read(fd, buf, sizeof(buf));119	close(fd);120	return rc == sizeof(buf) ?121	       memcmp(buf, magic, sizeof(buf)) == 0 : false;122}123