Compressed fragments and compressed data support
This commit is contained in:
parent
e4eaf62555
commit
8eef1f8244
3 changed files with 73 additions and 10 deletions
|
@ -51,13 +51,18 @@ struct grub_squash_super
|
|||
grub_uint32_t dummy1;
|
||||
grub_uint32_t creation_time;
|
||||
grub_uint32_t dummy2;
|
||||
grub_uint32_t dummy3[4];
|
||||
grub_uint32_t dummy3[2];
|
||||
grub_uint8_t flags;
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_INODES 1
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_DATA 2
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8
|
||||
grub_uint8_t dummy4[7];
|
||||
grub_uint16_t root_ino_offset;
|
||||
grub_uint16_t root_ino_chunk;
|
||||
grub_uint32_t dummy4;
|
||||
grub_uint32_t dummy5;
|
||||
grub_uint64_t total_size;
|
||||
grub_uint64_t exttbloffset;
|
||||
grub_uint32_t dummy5[2];
|
||||
grub_uint32_t dummy6[2];
|
||||
grub_uint64_t inodeoffset;
|
||||
grub_uint64_t diroffset;
|
||||
grub_uint64_t unk1offset;
|
||||
|
@ -399,8 +404,9 @@ static grub_ssize_t
|
|||
grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_uint64_t a;
|
||||
grub_uint64_t a, b;
|
||||
struct grub_squash_data *data = file->data;
|
||||
int compressed = 0;
|
||||
|
||||
if (grub_le_to_cpu16 (data->ino.fragment) == 0xffff)
|
||||
{
|
||||
|
@ -408,6 +414,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
a = grub_le_to_cpu32 (data->ino.chunk);
|
||||
else
|
||||
a = sizeof (struct grub_squash_super);
|
||||
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -418,12 +425,17 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
if (err)
|
||||
return -1;
|
||||
a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (data->ino.chunk);
|
||||
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS);
|
||||
}
|
||||
|
||||
a += grub_le_to_cpu32 (data->ino.offset) + file->offset;
|
||||
b = grub_le_to_cpu32 (data->ino.offset) + file->offset;
|
||||
|
||||
err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS,
|
||||
a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
|
||||
/* FIXME: cache uncompressed chunks. */
|
||||
if (compressed)
|
||||
err = grub_zlib_disk_read (file->device->disk, a, b, buf, len);
|
||||
else
|
||||
err = grub_disk_read (file->device->disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
|
||||
(a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
|
||||
if (err)
|
||||
return -1;
|
||||
return len;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/deflate.h>
|
||||
|
||||
/*
|
||||
|
@ -62,6 +63,9 @@ struct grub_gzio
|
|||
/* If input is in memory following fields are used instead of file. */
|
||||
grub_size_t mem_input_size, mem_input_off;
|
||||
grub_uint8_t *mem_input;
|
||||
grub_disk_addr_t disk_input_off;
|
||||
grub_disk_addr_t disk_input_start;
|
||||
grub_disk_t disk_input;
|
||||
/* The offset at which the data starts in the underlying file. */
|
||||
grub_off_t data_offset;
|
||||
/* The type of current block. */
|
||||
|
@ -383,8 +387,21 @@ get_byte (grub_gzio_t gzio)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset
|
||||
|| gzio->inbuf_d == INBUFSIZ)
|
||||
if (gzio->disk_input && (gzio->disk_input_off == gzio->data_offset
|
||||
|| gzio->inbuf_d == INBUFSIZ))
|
||||
{
|
||||
grub_disk_addr_t d = gzio->disk_input_start + gzio->disk_input_off;
|
||||
gzio->inbuf_d = 0;
|
||||
grub_disk_read (gzio->disk_input,
|
||||
d >> GRUB_DISK_SECTOR_BITS,
|
||||
d & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
INBUFSIZ, gzio->inbuf);
|
||||
gzio->disk_input_off += INBUFSIZ;
|
||||
}
|
||||
|
||||
if (gzio->file && (grub_file_tell (gzio->file)
|
||||
== (grub_off_t) gzio->data_offset
|
||||
|| gzio->inbuf_d == INBUFSIZ))
|
||||
{
|
||||
gzio->inbuf_d = 0;
|
||||
grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
|
||||
|
@ -402,8 +419,10 @@ gzio_seek (grub_gzio_t gzio, grub_off_t off)
|
|||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"attempt to seek outside of the file");
|
||||
else
|
||||
gzio->mem_input_off = gzio->data_offset;
|
||||
gzio->mem_input_off = off;
|
||||
}
|
||||
else if (gzio->disk_input)
|
||||
gzio->disk_input_off = off;
|
||||
else
|
||||
grub_file_seek (gzio->file, off);
|
||||
}
|
||||
|
@ -1297,6 +1316,34 @@ grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
|
|||
return ret;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
|
||||
grub_off_t off, char *outbuf, grub_size_t outsize)
|
||||
{
|
||||
grub_gzio_t gzio = 0;
|
||||
grub_ssize_t ret;
|
||||
|
||||
gzio = grub_zalloc (sizeof (*gzio));
|
||||
if (! gzio)
|
||||
return -1;
|
||||
|
||||
gzio->disk_input_off = 0;
|
||||
gzio->disk_input_start = zlibstart;
|
||||
gzio->disk_input = disk;
|
||||
|
||||
if (!test_zlib_header (gzio))
|
||||
{
|
||||
grub_free (gzio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = grub_gzio_read_real (gzio, off, outbuf, outsize);
|
||||
grub_free (gzio);
|
||||
|
||||
/* FIXME: Check Adler. */
|
||||
return ret < 0 ? grub_errno : GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct grub_fs grub_gzio_fs =
|
||||
|
|
|
@ -23,4 +23,8 @@ grub_ssize_t
|
|||
grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
|
||||
char *outbuf, grub_size_t outsize);
|
||||
|
||||
grub_err_t
|
||||
grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
|
||||
grub_off_t off, char *outbuf, grub_size_t outsize);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue