static int __init alloc_workspace(void)
{
	lzo_mem = vmalloc(LZO1X_MEM_COMPRESS);
	lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE));

	if (!lzo_mem || !lzo_compress_buf) {
		free_workspace();
		return -ENOMEM;
	}

	return 0;
}
Ejemplo n.º 2
0
static int __init alloc_workspace(void)
{
	lzo_mem = vmalloc(LZO1X_MEM_COMPRESS);
	lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE));

	if (!lzo_mem || !lzo_compress_buf) {
		printk(KERN_WARNING "Failed to allocate lzo deflate workspace\n");
		free_workspace();
		return -ENOMEM;
	}

	return 0;
}
Ejemplo n.º 3
0
static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len,
			  u64 *decompress_len)
{
	size_t new_len;
	size_t in_len;
	size_t out_len = 0;
	size_t tot_len;
	size_t tot_in;
	int ret;

	ret = lzo_init();
	if (ret != LZO_E_OK) {
		fprintf(stderr, "lzo init returned %d\n", ret);
		return -1;
	}

	tot_len = read_compress_length(inbuf);
	inbuf += LZO_LEN;
	tot_in = LZO_LEN;

	while (tot_in < tot_len) {
		in_len = read_compress_length(inbuf);

		if ((tot_in + LZO_LEN + in_len) > tot_len) {
			fprintf(stderr, "bad compress length %lu\n",
				(unsigned long)in_len);
			return -1;
		}

		inbuf += LZO_LEN;
		tot_in += LZO_LEN;

		new_len = lzo1x_worst_compress(PAGE_CACHE_SIZE);
		ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len,
					    (unsigned char *)outbuf,
					    (void *)&new_len, NULL);
		if (ret != LZO_E_OK) {
			fprintf(stderr, "failed to inflate: %d\n", ret);
			return -1;
		}
		out_len += new_len;
		outbuf += new_len;
		inbuf += in_len;
		tot_in += in_len;
	}

	*decompress_len = out_len;

	return 0;
}
Ejemplo n.º 4
0
static void allocate_lzo(void)
{
	big_oops_buf_sz = lzo1x_worst_compress(psinfo->bufsize);
	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
	if (big_oops_buf) {
		workspace = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
		if (!workspace) {
			pr_err("No memory for compression workspace; skipping compression\n");
			kfree(big_oops_buf);
			big_oops_buf = NULL;
		}
	} else {
		pr_err("No memory for uncompressed data; skipping compression\n");
		workspace = NULL;
	}
}
Ejemplo n.º 5
0
STATIC inline int INIT unlzo(u8 *input, int in_len,
                             int (*fill) (void *, unsigned int),
                             int (*flush) (void *, unsigned int),
                             u8 *output, int *posp,
                             void (*error_fn) (char *x))
{
    u8 skip = 0, r = 0;
    u32 src_len, dst_len;
    size_t tmp;
    u8 *in_buf, *in_buf_save, *out_buf;
    int ret = -1;

    set_error_fn(error_fn);

    if (output) {
        out_buf = output;
    } else if (!flush) {
        error("NULL output pointer and no flush function provided");
        goto exit;
    } else {
        out_buf = malloc(LZO_BLOCK_SIZE);
        if (!out_buf) {
            error("Could not allocate output buffer");
            goto exit;
        }
    }

    if (input && fill) {
        error("Both input pointer and fill function provided, don't know what to do");
        goto exit_1;
    } else if (input) {
        in_buf = input;
    } else if (!fill || !posp) {
        error("NULL input pointer and missing position pointer or fill function");
        goto exit_1;
    } else {
        in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
        if (!in_buf) {
            error("Could not allocate input buffer");
            goto exit_1;
        }
    }
    in_buf_save = in_buf;

    if (posp)
        *posp = 0;

    if (fill)
        fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));

    if (!parse_header(input, &skip)) {
        error("invalid header");
        goto exit_2;
    }
    in_buf += skip;

    if (posp)
        *posp = skip;

    for (;;) {
        /* read uncompressed block size */
        dst_len = get_unaligned_be32(in_buf);
        in_buf += 4;

        /* exit if last block */
        if (dst_len == 0) {
            if (posp)
                *posp += 4;
            break;
        }

        if (dst_len > LZO_BLOCK_SIZE) {
            error("dest len longer than block size");
            goto exit_2;
        }

        /* read compressed block size, and skip block checksum info */
        src_len = get_unaligned_be32(in_buf);
        in_buf += 8;

        if (src_len <= 0 || src_len > dst_len) {
            error("file corrupted");
            goto exit_2;
        }

        /* decompress */
        tmp = dst_len;

        /* When the input data is not compressed at all,
         * lzo1x_decompress_safe will fail, so call memcpy()
         * instead */
        if (unlikely(dst_len == src_len))
            memcpy(out_buf, in_buf, src_len);
        else {
            r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
                                      out_buf, &tmp);

            if (r != LZO_E_OK || dst_len != tmp) {
                error("Compressed data violation");
                goto exit_2;
            }
        }

        if (flush)
            flush(out_buf, dst_len);
        if (output)
            out_buf += dst_len;
        if (posp)
            *posp += src_len + 12;
        if (fill) {
            in_buf = in_buf_save;
            fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
        } else
            in_buf += src_len;
    }

    ret = 0;
exit_2:
    if (!input)
        free(in_buf);
exit_1:
    if (!output)
        free(out_buf);
exit:
    return ret;
}
Ejemplo n.º 6
0
static int zbufsize_lzo(size_t size)
{
	return lzo1x_worst_compress(size);
}
Ejemplo n.º 7
0
static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len,
			  u64 *decompress_len)
{
	size_t new_len;
	size_t in_len;
	size_t out_len = 0;
	size_t tot_len;
	size_t tot_in;
	int ret;

	ret = lzo_init();
	if (ret != LZO_E_OK) {
		fprintf(stderr, "lzo init returned %d\n", ret);
		return -1;
	}

	tot_len = read_compress_length(inbuf);
	inbuf += LZO_LEN;
	tot_in = LZO_LEN;

	while (tot_in < tot_len) {
		size_t mod_page;
		size_t rem_page;
		in_len = read_compress_length(inbuf);

		if ((tot_in + LZO_LEN + in_len) > tot_len) {
			fprintf(stderr, "bad compress length %lu\n",
				(unsigned long)in_len);
			return -1;
		}

		inbuf += LZO_LEN;
		tot_in += LZO_LEN;

		new_len = lzo1x_worst_compress(PAGE_CACHE_SIZE);
		ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len,
					    (unsigned char *)outbuf,
					    (void *)&new_len, NULL);
		if (ret != LZO_E_OK) {
			fprintf(stderr, "failed to inflate: %d\n", ret);
			return -1;
		}
		out_len += new_len;
		outbuf += new_len;
		inbuf += in_len;
		tot_in += in_len;

		/*
		 * If the 4 byte header does not fit to the rest of the page we
		 * have to move to the next one, unless we read some garbage
		 */
		mod_page = tot_in % PAGE_CACHE_SIZE;
		rem_page = PAGE_CACHE_SIZE - mod_page;
		if (rem_page < LZO_LEN) {
			inbuf += rem_page;
			tot_in += rem_page;
		}
	}

	*decompress_len = out_len;

	return 0;
}
Ejemplo n.º 8
0
int decompress_unlzo(u8 *input, int in_len,
				int (*fill) (void *, unsigned int),
				int (*flush) (void *, unsigned int),
				u8 *output, int *posp,
				void (*error) (char *x))
{
	u8 r = 0;
	int skip = 0;
	u32 src_len, dst_len;
	size_t tmp;
	u8 *in_buf, *in_buf_save, *out_buf;
	int ret = -1;

	if (output) {
		out_buf = output;
	} else if (!flush) {
		error("NULL output pointer and no flush function provided");
		goto exit;
	} else {
		out_buf = malloc(LZO_BLOCK_SIZE);
		if (!out_buf) {
			error("Could not allocate output buffer");
			goto exit;
		}
	}

	if (input && fill) {
		error("Both input pointer and fill function provided, don't know what to do");
		goto exit_1;
	} else if (input) {
		in_buf = input;
	} else if (!fill) {
		error("NULL input pointer and missing fill function");
		goto exit_1;
	} else {
		in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
		if (!in_buf) {
			error("Could not allocate input buffer");
			goto exit_1;
		}
	}
	in_buf_save = in_buf;

	if (posp)
		*posp = 0;

	if (fill) {
		/*
		 * Start from in_buf + HEADER_SIZE_MAX to make it possible
		 * to use memcpy() to copy the unused data to the beginning
		 * of the buffer. This way memmove() isn't needed which
		 * is missing from pre-boot environments of most archs.
		 */
		in_buf += HEADER_SIZE_MAX;
		in_len = fill(in_buf, HEADER_SIZE_MAX);
	}

	if (!parse_header(in_buf, &skip, in_len)) {
		error("invalid header");
		goto exit_2;
	}
	in_buf += skip;
	in_len -= skip;

	if (fill) {
		/* Move the unused data to the beginning of the buffer. */
		memcpy(in_buf_save, in_buf, in_len);
		in_buf = in_buf_save;
	}

	if (posp)
		*posp = skip;

	for (;;) {
		/* read uncompressed block size */
		if (fill && in_len < 4) {
			skip = fill(in_buf + in_len, 4 - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < 4) {
			error("file corrupted");
			goto exit_2;
		}
		dst_len = get_unaligned_be32(in_buf);
		in_buf += 4;
		in_len -= 4;

		/* exit if last block */
		if (dst_len == 0) {
			if (posp)
				*posp += 4;
			break;
		}

		if (dst_len > LZO_BLOCK_SIZE) {
			error("dest len longer than block size");
			goto exit_2;
		}

		/* read compressed block size, and skip block checksum info */
		if (fill && in_len < 8) {
			skip = fill(in_buf + in_len, 8 - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < 8) {
			error("file corrupted");
			goto exit_2;
		}
		src_len = get_unaligned_be32(in_buf);
		in_buf += 8;
		in_len -= 8;

		if (src_len <= 0 || src_len > dst_len) {
			error("file corrupted");
			goto exit_2;
		}

		/* decompress */
		if (fill && in_len < src_len) {
			skip = fill(in_buf + in_len, src_len - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < src_len) {
			error("file corrupted");
			goto exit_2;
		}
		tmp = dst_len;

		/* When the input data is not compressed at all,
		 * lzo1x_decompress_safe will fail, so call memcpy()
		 * instead */
		if (unlikely(dst_len == src_len))
			memcpy(out_buf, in_buf, src_len);
		else {
			r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
						out_buf, &tmp);

			if (r != LZO_E_OK || dst_len != tmp) {
				error("Compressed data violation");
				goto exit_2;
			}
		}

		if (flush && flush(out_buf, dst_len) != dst_len)
			goto exit_2;
		if (output)
			out_buf += dst_len;
		if (posp)
			*posp += src_len + 12;

		in_buf += src_len;
		in_len -= src_len;
		if (fill) {
			/*
			 * If there happens to still be unused data left in
			 * in_buf, move it to the beginning of the buffer.
			 * Use a loop to avoid memmove() dependency.
			 */
			if (in_len > 0)
				for (skip = 0; skip < in_len; ++skip)
					in_buf_save[skip] = in_buf[skip];
			in_buf = in_buf_save;
		}
	}

	ret = 0;
exit_2:
	if (!input)
		free(in_buf_save);
exit_1:
	if (!output)
		free(out_buf);
exit:
	return ret;
}
Ejemplo n.º 9
0
static int decompress_lzo(struct btrfs_root *root, unsigned char *inbuf,
			char *outbuf, u64 compress_len, u64 *decompress_len)
{
	size_t new_len;
	size_t in_len;
	size_t out_len = 0;
	size_t tot_len;
	size_t tot_in;
	int ret;

	ret = lzo_init();
	if (ret != LZO_E_OK) {
		error("lzo init returned %d", ret);
		return -1;
	}

	tot_len = read_compress_length(inbuf);
	inbuf += LZO_LEN;
	tot_in = LZO_LEN;

	while (tot_in < tot_len) {
		size_t mod_page;
		size_t rem_page;
		in_len = read_compress_length(inbuf);

		if ((tot_in + LZO_LEN + in_len) > tot_len) {
			error("bad compress length %lu",
				(unsigned long)in_len);
			return -1;
		}

		inbuf += LZO_LEN;
		tot_in += LZO_LEN;
		new_len = lzo1x_worst_compress(root->fs_info->sectorsize);
		ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len,
					    (unsigned char *)outbuf,
					    (void *)&new_len, NULL);
		if (ret != LZO_E_OK) {
			error("lzo decompress failed: %d", ret);
			return -1;
		}
		out_len += new_len;
		outbuf += new_len;
		inbuf += in_len;
		tot_in += in_len;

		/*
		 * If the 4 byte header does not fit to the rest of the page we
		 * have to move to the next one, unless we read some garbage
		 */
		mod_page = tot_in % root->fs_info->sectorsize;
		rem_page = root->fs_info->sectorsize - mod_page;
		if (rem_page < LZO_LEN) {
			inbuf += rem_page;
			tot_in += rem_page;
		}
	}

	*decompress_len = out_len;

	return 0;
}
STATIC inline int INIT unlzo(u8 *input, int in_len,
				int (*fill) (void *, unsigned int),
				int (*flush) (void *, unsigned int),
				u8 *output, int *posp,
				void (*error) (char *x))
{
	u8 r = 0;
	int skip = 0;
	u32 src_len, dst_len;
	size_t tmp;
	u8 *in_buf, *in_buf_save, *out_buf;
	int ret = -1;

	if (output) {
		out_buf = output;
	} else if (!flush) {
		error("NULL output pointer and no flush function provided");
		goto exit;
	} else {
		out_buf = malloc(LZO_BLOCK_SIZE);
		if (!out_buf) {
			error("Could not allocate output buffer");
			goto exit;
		}
	}

	if (input && fill) {
		error("Both input pointer and fill function provided, don't know what to do");
		goto exit_1;
	} else if (input) {
		in_buf = input;
	} else if (!fill) {
		error("NULL input pointer and missing fill function");
		goto exit_1;
	} else {
		in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
		if (!in_buf) {
			error("Could not allocate input buffer");
			goto exit_1;
		}
	}
	in_buf_save = in_buf;

	if (posp)
		*posp = 0;

	if (fill) {
		/*
                                                            
                                                             
                                                         
                                                         
   */
		in_buf += HEADER_SIZE_MAX;
		in_len = fill(in_buf, HEADER_SIZE_MAX);
	}

	if (!parse_header(in_buf, &skip, in_len)) {
		error("invalid header");
		goto exit_2;
	}
	in_buf += skip;
	in_len -= skip;

	if (fill) {
		/*                                                      */
		memcpy(in_buf_save, in_buf, in_len);
		in_buf = in_buf_save;
	}

	if (posp)
		*posp = skip;

	for (;;) {
		/*                              */
		if (fill && in_len < 4) {
			skip = fill(in_buf + in_len, 4 - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < 4) {
			error("file corrupted");
			goto exit_2;
		}
		dst_len = get_unaligned_be32(in_buf);
		in_buf += 4;
		in_len -= 4;

		/*                    */
		if (dst_len == 0) {
			if (posp)
				*posp += 4;
			break;
		}

		if (dst_len > LZO_BLOCK_SIZE) {
			error("dest len longer than block size");
			goto exit_2;
		}

		/*                                                          */
		if (fill && in_len < 8) {
			skip = fill(in_buf + in_len, 8 - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < 8) {
			error("file corrupted");
			goto exit_2;
		}
		src_len = get_unaligned_be32(in_buf);
		in_buf += 8;
		in_len -= 8;

		if (src_len <= 0 || src_len > dst_len) {
			error("file corrupted");
			goto exit_2;
		}

		/*            */
		if (fill && in_len < src_len) {
			skip = fill(in_buf + in_len, src_len - in_len);
			if (skip > 0)
				in_len += skip;
		}
		if (in_len < src_len) {
			error("file corrupted");
			goto exit_2;
		}
		tmp = dst_len;

		/*                                              
                                                      
             */
		if (unlikely(dst_len == src_len))
			memcpy(out_buf, in_buf, src_len);
		else {
			r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
						out_buf, &tmp);

			if (r != LZO_E_OK || dst_len != tmp) {
				error("Compressed data violation");
				goto exit_2;
			}
		}

		if (flush && flush(out_buf, dst_len) != dst_len)
			goto exit_2;
		if (output)
			out_buf += dst_len;
		if (posp)
			*posp += src_len + 12;

		in_buf += src_len;
		in_len -= src_len;
		if (fill) {
			/*
                                                      
                                                     
                                               
    */
			if (in_len > 0)
				for (skip = 0; skip < in_len; ++skip)
					in_buf_save[skip] = in_buf[skip];
			in_buf = in_buf_save;
		}
	}

	ret = 0;
exit_2:
	if (!input)
		free(in_buf_save);
exit_1:
	if (!output)
		free(out_buf);
exit:
	return ret;
}