Squashfs v4 support.

* Makefile.util.def (libgrubmods.a): Add squash4.
	* grub-core/Makefile.core.def (squash4): New module.
	* grub-core/fs/squash4.c: New file.
	* grub-core/io/gzio.c (grub_gzio): New members disk_input_off,
	disk_input_start, disk_input.
	(get_byte): Handle disk_input.
	(grub_zlib_disk_read): New function.
	* include/grub/deflate.h (grub_zlib_disk_read): New proto.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-05-15 11:58:22 +02:00
commit d4680a3556
6 changed files with 619 additions and 3 deletions

View file

@ -41,6 +41,7 @@
#include <grub/fs.h>
#include <grub/file.h>
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/deflate.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -64,6 +65,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. */
@ -384,8 +388,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);
@ -403,8 +420,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);
}
@ -1298,6 +1317,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 =