Пример #1
0
/* Allocate the XZ decoder state and register the character device. */
static int __init xz_dec_test_init(void)
{
	static const struct file_operations fileops = {
		.owner = THIS_MODULE,
		.open = &xz_dec_test_open,
		.release = &xz_dec_test_release,
		.write = &xz_dec_test_write
	};

	state = xz_dec_init(XZ_PREALLOC, DICT_MAX);
	if (state == NULL)
		return -ENOMEM;

	device_major = register_chrdev(0, DEVICE_NAME, &fileops);
	if (device_major < 0) {
		xz_dec_end(state);
		return device_major;
	}

	printk(KERN_INFO DEVICE_NAME ": module loaded\n");
	printk(KERN_INFO DEVICE_NAME ": Create a device node with "
			"'mknod " DEVICE_NAME " c %d 0' and write .xz files "
			"to it.\n", device_major);
	return 0;
}
Пример #2
0
int main(void)
{
	struct xz_buf b;
	struct xz_dec *s;
	enum xz_ret ret;

	xz_crc32_init();

	s = xz_dec_init(XZ_SINGLE, 0);
	if (s == NULL) {
		fputs("Initialization failed", stderr);
		return 1;
	}

	b.in = in;
	b.in_pos = 0;
	b.in_size = fread(in, 1, sizeof(in), stdin);
	b.out = out;
	b.out_pos = 0;
	b.out_size = sizeof(out);

	ret = xz_dec_run(s, &b);
	xz_dec_end(s);

	fwrite(out, 1, b.out_pos, stdout);
	fprintf(stderr, "%d\n", ret);

	return 0;
}
Пример #3
0
static int decrunch_xz(FILE *in, FILE *out)
{
	struct xz_buf b;
	struct xz_dec *state;
	unsigned char *membuf;
	int ret = 0;

	crc32_init_A();

	memset(&b, 0, sizeof(b));
	if ((membuf = malloc(2 * BUFFER_SIZE)) == NULL)
		return -1;

	b.in = membuf;
	b.out = membuf + BUFFER_SIZE;
	b.out_size = BUFFER_SIZE;

	/* Limit memory usage to 16M */
	state = xz_dec_init(XZ_DYNALLOC, 16 * 1024 * 1024);

	while (1) {
		enum xz_ret r;

		if (b.in_pos == b.in_size) {
			int rd = fread(membuf, 1, BUFFER_SIZE, in);
			if (rd < 0) {
				ret = -1;
				break;
			}
			b.in_size = rd;
			b.in_pos = 0;
		}

		r = xz_dec_run(state, &b);

		if (b.out_pos) {
			fwrite(b.out, 1, b.out_pos, out);
			b.out_pos = 0;
		}

		if (r == XZ_STREAM_END) {
			break;
		}

		if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) {
			ret = -1;
			break;
		}
	}

	xz_dec_end(state);
	free(membuf);

	return ret;
}
static int decompressor_xz_destroy(struct microfs_sb_info* sbi, void* data)
{
	struct decompressor_xz_data* xzdat = data;
	
	if (xzdat) {
		xz_dec_end(xzdat->xz_state);
		kfree(xzdat);
	}
	
	return 0;
}
Пример #5
0
/* Release everything, including the underlying file object.  */
static grub_err_t
grub_xzio_close (grub_file_t file)
{
  grub_xzio_t xzio = file->data;

  xz_dec_end (xzio->dec);

  grub_file_close (xzio->file);
  grub_free (xzio);

  /* Device must not be closed twice.  */
  file->device = 0;
  return grub_errno;
}
Пример #6
0
static void __exit xz_dec_test_exit(void)
{
	unregister_chrdev(device_major, DEVICE_NAME);
	xz_dec_end(state);
	printk(KERN_INFO DEVICE_NAME ": module unloaded\n");
}
Пример #7
0
static grub_file_t
grub_xzio_open (grub_file_t io)
{
  grub_file_t file;
  grub_xzio_t xzio;

  file = (grub_file_t) grub_zalloc (sizeof (*file));
  if (!file)
    return 0;

  xzio = grub_zalloc (sizeof (*xzio));
  if (!xzio)
    {
      grub_free (file);
      return 0;
    }

  xzio->file = io;
  xzio->saved_offset = 0;

  file->device = io->device;
  file->offset = 0;
  file->data = xzio;
  file->read_hook = 0;
  file->fs = &grub_xzio_fs;
  file->size = GRUB_FILE_SIZE_UNKNOWN;
  file->not_easly_seekable = 1;

  if (grub_file_tell (xzio->file) != 0)
    grub_file_seek (xzio->file, 0);

  /* Allocated 64KiB for dictionary.
   * Decoder will relocate if bigger is needed.  */
  xzio->dec = xz_dec_init (1 << 16);
  if (!xzio->dec)
    {
      grub_free (file);
      grub_free (xzio);
      return 0;
    }

  xzio->buf.in = xzio->inbuf;
  xzio->buf.in_pos = 0;
  xzio->buf.in_size = 0;
  xzio->buf.out = xzio->outbuf;
  xzio->buf.out_pos = 0;
  xzio->buf.out_size = XZBUFSIZ;

  /* FIXME: don't test footer on not easily seekable files.  */
  if (!test_header (file) || !test_footer (file))
    {
      grub_errno = GRUB_ERR_NONE;
      grub_file_seek (io, 0);
      xz_dec_end (xzio->dec);
      grub_free (xzio);
      grub_free (file);

      return io;
    }

  return file;
}
Пример #8
0
/*
 * This function implements the API defined in <linux/decompress/generic.h>.
 *
 * This wrapper will automatically choose single-call or multi-call mode
 * of the native XZ decoder API. The single-call mode can be used only when
 * both input and output buffers are available as a single chunk, i.e. when
 * fill() and flush() won't be used.
 */
STATIC int decompress_unxz(unsigned char *in, int in_size,
		     int (*fill)(void *dest, unsigned int size),
		     int (*flush)(void *src, unsigned int size),
		     unsigned char *out, int *in_used,
		     void (*error)(char *x))
{
	struct xz_buf b;
	struct xz_dec *s;
	enum xz_ret ret;
	bool must_free_in = false;

#if XZ_INTERNAL_CRC32
	xz_crc32_init();
#endif

	if (in_used != NULL)
		*in_used = 0;

	if (fill == NULL && flush == NULL)
		s = xz_dec_init(XZ_SINGLE, 0);
	else
		s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);

	if (s == NULL)
		goto error_alloc_state;

	if (flush == NULL) {
		b.out = out;
		b.out_size = (size_t)-1;
	} else {
		b.out_size = XZ_IOBUF_SIZE;
		b.out = MALLOC(XZ_IOBUF_SIZE);
		if (b.out == NULL)
			goto error_alloc_out;
	}

	if (in == NULL) {
		must_free_in = true;
		in = MALLOC(XZ_IOBUF_SIZE);
		if (in == NULL)
			goto error_alloc_in;
	}

	b.in = in;
	b.in_pos = 0;
	b.in_size = in_size;
	b.out_pos = 0;

	if (fill == NULL && flush == NULL) {
		ret = xz_dec_run(s, &b);
	} else {
		do {
			if (b.in_pos == b.in_size && fill != NULL) {
				if (in_used != NULL)
					*in_used += b.in_pos;

				b.in_pos = 0;

				in_size = fill(in, XZ_IOBUF_SIZE);
				if (in_size < 0) {
					/*
					 * This isn't an optimal error code
					 * but it probably isn't worth making
					 * a new one either.
					 */
					ret = XZ_BUF_ERROR;
					break;
				}

				b.in_size = in_size;
			}

			ret = xz_dec_run(s, &b);

			if (flush != NULL && (b.out_pos == b.out_size
					|| (ret != XZ_OK && b.out_pos > 0))) {
				/*
				 * Setting ret here may hide an error
				 * returned by xz_dec_run(), but probably
				 * it's not too bad.
				 */
				if (flush(b.out, b.out_pos) != (long)b.out_pos)
					ret = XZ_BUF_ERROR;

				b.out_pos = 0;
			}
		} while (ret == XZ_OK);

		if (must_free_in)
			FREE(in);

		if (flush != NULL)
			FREE(b.out);
	}

	if (in_used != NULL)
		*in_used += b.in_pos;

	xz_dec_end(s);

	switch (ret) {
	case XZ_STREAM_END:
		return 0;

	case XZ_MEM_ERROR:
		/* This can occur only in multi-call mode. */
		error("XZ decompressor ran out of memory");
		break;

	case XZ_FORMAT_ERROR:
		error("Input is not in the XZ format (wrong magic bytes)");
		break;

	case XZ_OPTIONS_ERROR:
		error("Input was encoded with settings that are not "
				"supported by this XZ decoder");
		break;

	case XZ_DATA_ERROR:
	case XZ_BUF_ERROR:
		error("XZ-compressed data is corrupt");
		break;

	default:
		error("Bug in the XZ decompressor");
		break;
	}

	return -1;

error_alloc_in:
	if (flush != NULL)
		FREE(b.out);

error_alloc_out:
	xz_dec_end(s);

error_alloc_state:
	error("XZ decompressor ran out of memory");
	return -1;
}
Пример #9
0
static void crypto_xz_decomp_exit(struct xz_comp_ctx *ctx)
{
	xz_dec_end(ctx->decomp_state);
}
Пример #10
0
static errlHndl_t load_pnor_section(PNOR::SectionId i_section,
        uint64_t i_physAddr)
{
    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ENTER_MRK"load_pnor_section()");
    errlHndl_t err = nullptr;

#ifdef CONFIG_SECUREBOOT
    // Securely load section
    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"load_pnor_section: secure section load of secId=0x%X (%s)",
              i_section, PNOR::SectionIdToString(i_section));
    err = PNOR::loadSecureSection(i_section);
    if (err)
    {
        return err;
    }
    // Do not need to unload since we have plenty of memory at this point.
#endif

    // Get the section info from PNOR.
    PNOR::SectionInfo_t pnorSectionInfo;
    err = PNOR::getSectionInfo( i_section, pnorSectionInfo );
    if( err != nullptr )
    {
        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                 "load_pnor_section: Could not get section info from %x",
                  i_section);
        return err;
    }

    // XZ repository: http:git.tukaani.org/xz.git
    // Header specifics can be found in xz/doc/xz-file-format.txt
    const uint8_t HEADER_MAGIC[]= { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
    uint8_t* l_pnor_header = reinterpret_cast<uint8_t *>(pnorSectionInfo.vaddr);

    bool l_pnor_is_XZ_compressed = (0 == memcmp(l_pnor_header,
                               HEADER_MAGIC, sizeof(HEADER_MAGIC)));

    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
             "load_pnor_section: is XZ_compressed: %d",
              l_pnor_is_XZ_compressed);

    // This assumes that the maximum decompression ratio will always be less
    // than 1:16 (compressed:uncompressed).  This works because XZ compression
    // is usually 14.1%, the decompressor does not need the exact size, and
    // we have all of mainstore memory at this point.
    uint32_t uncompressedPayloadSize = l_pnor_is_XZ_compressed ?
            (pnorSectionInfo.size * 16) : pnorSectionInfo.size;


    const uint32_t originalPayloadSize = pnorSectionInfo.size;

    printk( "Loading PNOR section %d (%s) %d bytes @0x%lx\n",
            i_section,
            pnorSectionInfo.name,
            originalPayloadSize,
            i_physAddr );

    void * loadAddr = NULL;
    // Map in the physical memory we are loading into.
    // If we are not xz compressed, the uncompressedSize
    // is equal to the original size.
    loadAddr = mm_block_map( reinterpret_cast<void*>( i_physAddr ),
                             uncompressedPayloadSize );

    // Print out inital progress bar.
#ifdef CONFIG_CONSOLE
    const int progressSteps = 80;
    int progress = 0;
    for ( int i = 0; i < progressSteps; ++i )
    {
        printk( "." );
    }
    printk( "\r" );
#endif

    if(!l_pnor_is_XZ_compressed)
    {
        // Load the data block by block and update the progress bar.
        const uint32_t BLOCK_SIZE = 4096;
        for ( uint32_t i = 0; i < originalPayloadSize; i += BLOCK_SIZE )
        {
            memcpy( reinterpret_cast<void*>(
                      reinterpret_cast<uint64_t>(loadAddr) + i ),
                    reinterpret_cast<void*>( pnorSectionInfo.vaddr + i ),
                    std::min( originalPayloadSize - i, BLOCK_SIZE ) );
#ifdef CONFIG_CONSOLE
            for ( int new_progress = (i * progressSteps) /
                  originalPayloadSize;
                  progress <= new_progress; progress++ )
            {
                printk( "=" );
            }
#endif
        }
#ifdef CONFIG_CONSOLE
        printk( "\n" );
#endif
    }

    if(l_pnor_is_XZ_compressed)
    {
        struct xz_buf b;
        struct xz_dec *s;
        enum xz_ret ret;

        xz_crc32_init();
        s = xz_dec_init(XZ_SINGLE, 0);
        if(s == NULL)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK
                     "load_pnor_section: XZ Embedded Initialization failed");
            return err;
        }

        static const uint64_t compressed_SIZE = originalPayloadSize;
        static const uint64_t decompressed_SIZE = uncompressedPayloadSize;

        b.in = reinterpret_cast<uint8_t *>( pnorSectionInfo.vaddr);
        b.in_pos = 0;
        b.in_size = compressed_SIZE;
        b.out = reinterpret_cast<uint8_t *>(loadAddr);
        b.out_pos = 0;
        b.out_size = decompressed_SIZE;

        ret = xz_dec_run(s, &b);

        if(ret == XZ_STREAM_END)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                     "load_pnor_section: The %s section was decompressed.",
                      pnorSectionInfo.name);
        }else
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK
                     "load_pnor_section: xz-embedded returned an error, ",
                     "the ret is %d",ret);

            /*@
             * @errortype
             * @reasoncode       fapi::RC_INVALID_RETURN_XZ_CODE
             * @severity         ERRORLOG::ERRL_SEV_UNRECOVERABLE
             * @moduleid         fapi::MOD_START_XZ_PAYLOAD
             * @devdesc          xz-embedded has returned an error.
             *                   the return code can be found in xz.h
             * @custdesc         Error uncompressing payload image from
             *                   boot flash
             * @userdata1        Return code from xz-embedded
             * @userdata2[0:31]  Original Payload Size
             * @userdata2[32:63] Uncompressed Payload Size
             */
            err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                            fapi::MOD_START_XZ_PAYLOAD,
                            fapi::RC_INVALID_RETURN_XZ_CODE,
                            ret,TWO_UINT32_TO_UINT64(
                                    originalPayloadSize,
                                    uncompressedPayloadSize));
            err->addProcedureCallout(HWAS::EPUB_PRC_PHYP_CODE,
                            HWAS::SRCI_PRIORITY_HIGH);

        }
        //Clean up memory
        xz_dec_end(s);

    }

    int rc = 0;
    rc = mm_block_unmap(reinterpret_cast<void *>(loadAddr));
    if(rc)
    {
        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK
                 "load_pnor_section: mm_block_unmap returned 1");

        /*@
         * @errortype
         * @reasoncode      fapi::RC_MM_UNMAP_ERR
         * @severity        ERRORLOG::ERRL_SEV_UNRECOVERABLE
         * @moduleid        fapi::MOD_START_XZ_PAYLOAD
         * @devdesc         mm_block_unmap returned incorrectly with 0
         * @custdesc        Error unmapping memory section
         */
        err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
                                      fapi::MOD_START_XZ_PAYLOAD,
                                      fapi::RC_MM_UNMAP_ERR,
                                      0,0,0);
    }
    return err;
}
Пример #11
0
int main(int argc, char **argv, char *envp[])
{
	struct xz_buf b;
	struct xz_dec *s;
	enum xz_ret ret;
	const char *msg;

	if (argc >= 2 && strcmp(argv[1], "--help") == 0) {
		fputs("Uncompress a .xz file from stdin to stdout.\n"
				"Arguments other than `--help' are ignored.\n",
				stdout);
		return 0;
	}

	xz_crc32_init();

	/*
	 * Support up to 64 MiB dictionary. The actually needed memory
	 * is allocated once the headers have been parsed.
	 */
	s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
	if (s == NULL) {
		msg = "Memory allocation failed\n";
		goto error;
	}

	b.in = in;
	b.in_pos = 0;
	b.in_size = BUFSIZ;
	b.out = out;
	b.out_pos = 0;
	b.out_size = BUFSIZ;
//     TODO add error checking
        char temp_dir_name[] = "/tmp/unv_installer_XXXXXX"; /* TODO: find tmpdir, don't assume it is /tmp */
        mkdtemp(temp_dir_name);
        char temp_file_name[256];
        sprintf(temp_file_name, "%s/installer", temp_dir_name);
        FILE* temp_fp = fopen(temp_file_name, "w");
        while (true) {
		ret = xz_dec_run(s, &b);
		/*So that xz_dec_run will consume another BUFSIZ bytes (it reads from b.in_pos till b.in_size)*/
                if (fwrite(b.out, 1, b.out_pos, temp_fp) != b.out_pos) {
                        msg = "Write error\n";
                        goto error;
                    }

		if (ret == XZ_OK){
                    b.in_size+=BUFSIZ;
                    b.out_pos=0;
                    continue;
                }

#ifdef XZ_DEC_ANY_CHECK
		if (ret == XZ_UNSUPPORTED_CHECK) {
			fputs(argv[0], stderr);
			fputs(": ", stderr);
			fputs("Unsupported check; not verifying "
					"file integrity\n", stderr);
			continue;
		}
#endif

		switch (ret) {
		case XZ_STREAM_END:
			xz_dec_end(s);
                        chmod(temp_file_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
                        fclose(temp_fp);
                        printf("%s\n", temp_file_name);
                        int i = 0;
                        while (envp[i] != NULL){
                            i++;
                        }
                        char **env = malloc((i+1)*sizeof(char *));
                        memcpy(env, envp, i*sizeof(char *));
                        char var[256];
                        sprintf(var, "LD_LIBRARY_PATH=%s", temp_dir_name);
                        env[i] = var;
                        env[i+1] = (char*) NULL;
//                         {"LD_LIBRARY_PATH=", (char *) NULL};
                        execle(temp_file_name, temp_file_name, (char*) NULL, env);
                        printf("Weird\n");
                        return 1;  /*Will only occur if execl call failed.*/

		case XZ_MEM_ERROR:
			msg = "Memory allocation failed\n";
			goto error;

		case XZ_MEMLIMIT_ERROR:
			msg = "Memory usage limit reached\n";
			goto error;

		case XZ_FORMAT_ERROR:
			msg = "Not a .xz file\n";
			goto error;

		case XZ_OPTIONS_ERROR:
			msg = "Unsupported options in the .xz headers\n";
			goto error;

		case XZ_DATA_ERROR:
		case XZ_BUF_ERROR:
			msg = "File is corrupt\n";
			goto error;

		default:
			msg = "Bug!\n";
			goto error;
		}
	}


error:
	xz_dec_end(s);
	fputs(argv[0], stderr);
	fputs(": ", stderr);
	fputs(msg, stderr);
	return 1;
}
Пример #12
0
/**
 * Compress command: tar -c car/ | xz --check=crc32 --lzma2=preset=6e,dict=512Ki > car.tar.xz
 *																				 | ./iap 0.0.0.0 'target file'
 *
 * Decompress command: dxz 'src file' 'dest file'
 *                     dxz 'src file' | tar xv -C 
 */
int dxz_file(FILE *src, FILE *dest)
{
	struct xz_buf b;
	struct xz_dec *s;
	int ret;
	int show_flag = 0;

	xz_crc32_init();
	s = xz_dec_init(XZ_PREALLOC, XZ_IN_BUFFSIZE);
	if (NULL == s)
	{
		DBG("Can not initialzation decompress object!\n");
		return -1;
	}

	b.in = xz_ibuf;
	b.in_pos = 0;
	b.out = xz_obuf;
	b.out_pos = 0;
	b.out_size = sizeof(xz_obuf);
	do {
		if (0 == b.in_pos)
		{
			while(!CAN_READ_FILE(fileno(src), 10));

			b.in_size = fread(xz_ibuf, 1, sizeof(xz_ibuf), src);

			if (!b.in_size)
			{
				return -1;
			}

			if (!show_flag)
			{
				show_flag = ~show_flag;
				disp_share_stat("正在解包.");
			}
		}

		ret = xz_dec_run(s, &b);

		disp_share_process();

		if (b.in_pos == b.in_size)
			b.in_pos = 0;

		if (b.out_pos == b.out_size)
		{
			if (fwrite(xz_obuf, 1, b.out_size, dest) != b.out_size)
			{
				DBG("Write file fail!\n");
				ret = -1;
				goto end;
			}
			b.out_pos = 0;
	
		}

	}while (XZ_OK == ret);

	if (XZ_STREAM_END == ret)
	{
		if (b.out_pos)
		{
			if (fwrite(xz_obuf, 1, b.out_pos, dest) != b.out_pos)
			{
				DBG("Write file fail!\n");
				ret = -1;
				goto end;
			}
		}
		ret = 0;
		disp_share_stat("解包完成!\n");
	}
	else
	{
		DBG("Decompress fail!(ret: %d)\n", ret);
		ret = -1;
	}

end:
	xz_dec_end(s);
	if (ret != 0)
	{
		DBG("Processing fail!\n");
		disp_share_stat("解包失败!\n");
		sleep(2);
	}
	return ret;
}
Пример #13
0
/*
 * This function implements the API defined in <linux/decompress/generic.h>.
 *
 * This wrapper will automatically choose single-call or multi-call mode
 * of the native XZ decoder API. The single-call mode can be used only when
 * both input and output buffers are available as a single chunk, i.e. when
 * fill() and flush() won't be used.
 *
 * This API doesn't provide a way to specify the maximum dictionary size
 * for the multi-call mode of the native XZ decoder API. We will use
 * DICT_MAX bytes, which will be allocated with vmalloc().
 */
STATIC int XZ_FUNC unxz(/*const*/ unsigned char *in, int in_size,
		int (*fill)(void *dest, unsigned int size),
		int (*flush)(/*const*/ void *src, unsigned int size),
		unsigned char *out, int *in_used,
		void (*error)(/*const*/ char *x))
{
	struct xz_buf b;
	struct xz_dec *s;
	enum xz_ret ret;

	xz_crc32_init();

	if (in != NULL && out != NULL)
		s = xz_dec_init(XZ_SINGLE, 0);
	else
		s = xz_dec_init(XZ_PREALLOC /*FIXME*/, DICT_MAX);

	if (s == NULL)
		goto error_alloc_state;

	b.in = in;
	b.in_pos = 0;
	b.in_size = in_size;
	b.out_pos = 0;

	if (in_used != NULL)
		*in_used = 0;

	if (fill == NULL && flush == NULL) {
		b.out = out;
		b.out_size = (size_t)-1;
		ret = xz_dec_run(s, &b);
	} else {
		b.out_size = XZ_IOBUF_SIZE;
		b.out = kmalloc(XZ_IOBUF_SIZE, GFP_KERNEL);
		if (b.out == NULL)
			goto error_alloc_out;

		if (fill != NULL) {
			in = kmalloc(XZ_IOBUF_SIZE, GFP_KERNEL);
			if (in == NULL)
				goto error_alloc_in;

			b.in = in;
		}

		do {
			if (b.in_pos == b.in_size && fill != NULL) {
				if (in_used != NULL)
					*in_used += b.in_pos;

				b.in_pos = 0;

				in_size = fill(in, XZ_IOBUF_SIZE);
				if (in_size < 0) {
					/*
					 * This isn't an optimal error code
					 * but it probably isn't worth making
					 * a new one either.
					 */
					ret = XZ_BUF_ERROR;
					break;
				}

				b.in_size = in_size;
			}

			ret = xz_dec_run(s, &b);

			if (b.out_pos == b.out_size || ret != XZ_OK) {
				/*
				 * Setting ret here may hide an error
				 * returned by xz_dec_run(), but probably
				 * it's not too bad.
				 */
				if (flush(b.out, b.out_pos) != (int)b.out_pos)
					ret = XZ_BUF_ERROR;

				b.out_pos = 0;
			}
		} while (ret == XZ_OK);

		if (fill != NULL)
			kfree(in);

		kfree(b.out);
	}

	if (in_used != NULL)
		*in_used += b.in_pos;

	xz_dec_end(s);

	switch (ret) {
	case XZ_STREAM_END:
		return 0;

	case XZ_MEMLIMIT_ERROR:
		/* This can occur only in multi-call mode. */
		error("Multi-call XZ decompressor limits "
				"the LZMA2 dictionary to 1 MiB");
		break;

	case XZ_FORMAT_ERROR:
		error("Input is not in the XZ format (wrong magic bytes)");
		break;

	case XZ_OPTIONS_ERROR:
		error("Input was encoded with settings that are not "
				"supported by this XZ decoder");
		break;

	case XZ_DATA_ERROR:
		error("XZ-compressed data is corrupt");
		break;

	case XZ_BUF_ERROR:
		error("Output buffer is too small or the "
				"XZ-compressed data is corrupt");
		break;

	default:
		error("Bug in the XZ decompressor");
		break;
	}

	return -1;

error_alloc_in:
	kfree(b.out);

error_alloc_out:
	xz_dec_end(s);

error_alloc_state:
	error("XZ decompressor ran out of memory");
	return -1;
}
Пример #14
0
XzStreamReader::~XzStreamReader()
{
	xz_dec_end(m_decoder);
}
Пример #15
0
int xz_decompress(unsigned char *encoded, int encoded_size,
    unsigned char **decoded, int *decoded_size)
{
    static int xz_initialized = 0;
    enum xz_ret ret;
    struct xz_dec *xz;
    struct xz_buf buf;
    unsigned char *dec_buffer;
    unsigned char *temp;
    int dec_size;

    if (!xz_initialized)
    {
        xz_crc32_init();
        xz_initialized = 1;
    }

    *decoded = NULL;
    *decoded_size = 0;

    buf.in = encoded;
    buf.in_pos = 0;
    buf.in_size = encoded_size;

    dec_size = BUFFER_INCREMENT;
    dec_buffer = (unsigned char *)malloc(dec_size);
    if (!dec_buffer)
    {
        return 0;
    }

    buf.out = dec_buffer;
    buf.out_pos = 0;
    buf.out_size = dec_size;

    xz = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
    if (!xz)
    {
        free(dec_buffer);
        return 0;
    }

    do
    {
        ret = xz_dec_run(xz, &buf);
        if (ret == XZ_OK)
        {
            /* things are okay, but more buffer space is needed */
            dec_size += BUFFER_INCREMENT;
            temp = realloc(dec_buffer, dec_size);
            if (!temp)
            {
                free(dec_buffer);
                xz_dec_end(xz);
                return 0;
            }
            else
                dec_buffer = temp;
            buf.out_size = dec_size;
            buf.out = dec_buffer;
        }
        else
        {
            /* any other status is an exit condition (either error or stream end) */
            break;
        }
    } while (ret != XZ_STREAM_END);

    if (ret == XZ_STREAM_END)
    {
        /* resize the final buffer */
        dec_size = buf.out_pos;
        temp = realloc(dec_buffer, dec_size);
        if (!temp)
        {
            free(dec_buffer);
            xz_dec_end(xz);
            return 0;
        }
        *decoded = temp;
        *decoded_size = dec_size;
        xz_dec_end(xz);
        return 1;
    }
    else
    {
        xz_dec_end(xz);
        free(dec_buffer);
        return 0;
    }
}