BtrFS support. Written by me (Vladimir) with important bugfixes and
even more important testing by Colin. * Makefile.util.def (libgrubmods.a): Add crc.c and gzio.c * grub-core/Makefile.core.def (btrfs): Add crc.c. * grub-core/fs/btrfs.c: Stub replaced with real implementation. * grub-core/io/gzio.c (grub_gzio): New fields mem_input_size, mem_input_off and mem_input. All users updated to accept in-RAM input. (gzio_seek): New function. (test_zlib_header): Likewise. (grub_gzio_read): Likewise. (grub_zlib_decompress): Likewise. * grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo): Accept partial and non-virtual mounts. (grub_guess_root_device): Do rescanning after device_from_mountinfo to avoid receiving /dev/dm-X as device. * grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Handle bind and partial mounts. * grub-core/lib/crc.c: New file. * include/grub/deflate.h: Likewise. * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): New proto. * include/grub/lib/crc.h: New file.
This commit is contained in:
commit
fe6b2cbaa6
11 changed files with 1711 additions and 100 deletions
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
||||||
|
2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
2011-04-11 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
BtrFS support. Written by me (Vladimir) with important bugfixes and
|
||||||
|
even more important testing by Colin.
|
||||||
|
|
||||||
|
* Makefile.util.def (libgrubmods.a): Add crc.c and gzio.c
|
||||||
|
* grub-core/Makefile.core.def (btrfs): Add crc.c.
|
||||||
|
* grub-core/fs/btrfs.c: Stub replaced with real implementation.
|
||||||
|
* grub-core/io/gzio.c (grub_gzio): New fields mem_input_size,
|
||||||
|
mem_input_off and mem_input. All users updated to accept in-RAM input.
|
||||||
|
(gzio_seek): New function.
|
||||||
|
(test_zlib_header): Likewise.
|
||||||
|
(grub_gzio_read): Likewise.
|
||||||
|
(grub_zlib_decompress): Likewise.
|
||||||
|
* grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo):
|
||||||
|
Accept partial and non-virtual mounts.
|
||||||
|
(grub_guess_root_device): Do rescanning after device_from_mountinfo to
|
||||||
|
avoid receiving /dev/dm-X as device.
|
||||||
|
* grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root):
|
||||||
|
Handle bind and partial mounts.
|
||||||
|
* grub-core/lib/crc.c: New file.
|
||||||
|
* include/grub/deflate.h: Likewise.
|
||||||
|
* include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): New
|
||||||
|
proto.
|
||||||
|
* include/grub/lib/crc.h: New file.
|
||||||
|
|
||||||
2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
Implement automatic module license checking according to new GNU
|
Implement automatic module license checking according to new GNU
|
||||||
|
|
|
@ -83,6 +83,7 @@ library = {
|
||||||
common = grub-core/lib/LzFind.c;
|
common = grub-core/lib/LzFind.c;
|
||||||
common = grub-core/lib/LzmaEnc.c;
|
common = grub-core/lib/LzmaEnc.c;
|
||||||
common = grub-core/lib/pbkdf2.c;
|
common = grub-core/lib/pbkdf2.c;
|
||||||
|
common = grub-core/lib/crc.c;
|
||||||
common = grub-core/normal/datetime.c;
|
common = grub-core/normal/datetime.c;
|
||||||
common = grub-core/normal/misc.c;
|
common = grub-core/normal/misc.c;
|
||||||
common = grub-core/partmap/acorn.c;
|
common = grub-core/partmap/acorn.c;
|
||||||
|
@ -98,6 +99,7 @@ library = {
|
||||||
common = grub-core/script/main.c;
|
common = grub-core/script/main.c;
|
||||||
common = grub-core/script/script.c;
|
common = grub-core/script/script.c;
|
||||||
common = grub-core/script/argv.c;
|
common = grub-core/script/argv.c;
|
||||||
|
common = grub-core/io/gzio.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
|
|
|
@ -906,6 +906,7 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = btrfs;
|
name = btrfs;
|
||||||
common = fs/btrfs.c;
|
common = fs/btrfs.c;
|
||||||
|
common = lib/crc.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
|
1410
grub-core/fs/btrfs.c
1410
grub-core/fs/btrfs.c
File diff suppressed because it is too large
Load diff
|
@ -41,6 +41,7 @@
|
||||||
#include <grub/fs.h>
|
#include <grub/fs.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
|
#include <grub/deflate.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -60,6 +61,9 @@ struct grub_gzio
|
||||||
{
|
{
|
||||||
/* The underlying file object. */
|
/* The underlying file object. */
|
||||||
grub_file_t file;
|
grub_file_t file;
|
||||||
|
/* 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;
|
||||||
/* The offset at which the data starts in the underlying file. */
|
/* The offset at which the data starts in the underlying file. */
|
||||||
grub_off_t data_offset;
|
grub_off_t data_offset;
|
||||||
/* The type of current block. */
|
/* The type of current block. */
|
||||||
|
@ -102,7 +106,7 @@ typedef struct grub_gzio *grub_gzio_t;
|
||||||
static struct grub_fs grub_gzio_fs;
|
static struct grub_fs grub_gzio_fs;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
static void initialize_tables (grub_file_t file);
|
static void initialize_tables (grub_gzio_t);
|
||||||
|
|
||||||
/* Eat variable-length header fields. */
|
/* Eat variable-length header fields. */
|
||||||
static int
|
static int
|
||||||
|
@ -164,7 +168,7 @@ typedef unsigned short ush;
|
||||||
typedef unsigned long ulg;
|
typedef unsigned long ulg;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
test_header (grub_file_t file)
|
test_gzip_header (grub_file_t file)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
grub_uint16_t magic;
|
grub_uint16_t magic;
|
||||||
|
@ -227,7 +231,7 @@ test_header (grub_file_t file)
|
||||||
file->size = grub_le_to_cpu32 (orig_len);
|
file->size = grub_le_to_cpu32 (orig_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize_tables (file);
|
initialize_tables (gzio);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -367,13 +371,18 @@ static ush mask_bits[] =
|
||||||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(file))<<k;k+=8;}} while (0)
|
#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<<k;k+=8;}} while (0)
|
||||||
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
|
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_byte (grub_file_t file)
|
get_byte (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
grub_gzio_t gzio = file->data;
|
if (gzio->mem_input)
|
||||||
|
{
|
||||||
|
if (gzio->mem_input_off < gzio->mem_input_size)
|
||||||
|
return gzio->mem_input[gzio->mem_input_off++];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset
|
if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset
|
||||||
|| gzio->inbuf_d == INBUFSIZ)
|
|| gzio->inbuf_d == INBUFSIZ)
|
||||||
|
@ -385,11 +394,26 @@ get_byte (grub_file_t file)
|
||||||
return gzio->inbuf[gzio->inbuf_d++];
|
return gzio->inbuf[gzio->inbuf_d++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gzio_seek (grub_gzio_t gzio, grub_off_t off)
|
||||||
|
{
|
||||||
|
if (gzio->mem_input)
|
||||||
|
{
|
||||||
|
if (off > gzio->mem_input_size)
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"attempt to seek outside of the file");
|
||||||
|
else
|
||||||
|
gzio->mem_input_off = gzio->data_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_file_seek (gzio->file, off);
|
||||||
|
}
|
||||||
|
|
||||||
/* more function prototypes */
|
/* more function prototypes */
|
||||||
static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *,
|
static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *,
|
||||||
struct huft **, int *);
|
struct huft **, int *);
|
||||||
static int huft_free (struct huft *);
|
static int huft_free (struct huft *);
|
||||||
static int inflate_codes_in_window (grub_file_t);
|
static int inflate_codes_in_window (grub_gzio_t);
|
||||||
|
|
||||||
|
|
||||||
/* Given a list of code lengths and a maximum table size, make a set of
|
/* Given a list of code lengths and a maximum table size, make a set of
|
||||||
|
@ -616,7 +640,7 @@ huft_free (struct huft *t)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
inflate_codes_in_window (grub_file_t file)
|
inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
register unsigned e; /* table entry flag/number of extra bits */
|
register unsigned e; /* table entry flag/number of extra bits */
|
||||||
unsigned n, d; /* length and index for copy */
|
unsigned n, d; /* length and index for copy */
|
||||||
|
@ -625,7 +649,6 @@ inflate_codes_in_window (grub_file_t file)
|
||||||
unsigned ml, md; /* masks for bl and bd bits */
|
unsigned ml, md; /* masks for bl and bd bits */
|
||||||
register ulg b; /* bit buffer */
|
register ulg b; /* bit buffer */
|
||||||
register unsigned k; /* number of bits in bit buffer */
|
register unsigned k; /* number of bits in bit buffer */
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* make local copies of globals */
|
/* make local copies of globals */
|
||||||
d = gzio->inflate_d;
|
d = gzio->inflate_d;
|
||||||
|
@ -753,11 +776,10 @@ inflate_codes_in_window (grub_file_t file)
|
||||||
/* get header for an inflated type 0 (stored) block. */
|
/* get header for an inflated type 0 (stored) block. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_stored_block (grub_file_t file)
|
init_stored_block (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
register ulg b; /* bit buffer */
|
register ulg b; /* bit buffer */
|
||||||
register unsigned k; /* number of bits in bit buffer */
|
register unsigned k; /* number of bits in bit buffer */
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* make local copies of globals */
|
/* make local copies of globals */
|
||||||
b = gzio->bb; /* initialize bit buffer */
|
b = gzio->bb; /* initialize bit buffer */
|
||||||
|
@ -787,11 +809,10 @@ init_stored_block (grub_file_t file)
|
||||||
Huffman tables. */
|
Huffman tables. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_fixed_block (grub_file_t file)
|
init_fixed_block (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
int i; /* temporary variable */
|
int i; /* temporary variable */
|
||||||
unsigned l[288]; /* length list for huft_build */
|
unsigned l[288]; /* length list for huft_build */
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* set up literal table */
|
/* set up literal table */
|
||||||
for (i = 0; i < 144; i++)
|
for (i = 0; i < 144; i++)
|
||||||
|
@ -834,7 +855,7 @@ init_fixed_block (grub_file_t file)
|
||||||
/* get header for an inflated type 2 (dynamic Huffman codes) block. */
|
/* get header for an inflated type 2 (dynamic Huffman codes) block. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_dynamic_block (grub_file_t file)
|
init_dynamic_block (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
int i; /* temporary variables */
|
int i; /* temporary variables */
|
||||||
unsigned j;
|
unsigned j;
|
||||||
|
@ -847,7 +868,6 @@ init_dynamic_block (grub_file_t file)
|
||||||
unsigned ll[286 + 30]; /* literal/length and distance code lengths */
|
unsigned ll[286 + 30]; /* literal/length and distance code lengths */
|
||||||
register ulg b; /* bit buffer */
|
register ulg b; /* bit buffer */
|
||||||
register unsigned k; /* number of bits in bit buffer */
|
register unsigned k; /* number of bits in bit buffer */
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* make local bit buffer */
|
/* make local bit buffer */
|
||||||
b = gzio->bb;
|
b = gzio->bb;
|
||||||
|
@ -978,11 +998,10 @@ init_dynamic_block (grub_file_t file)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_new_block (grub_file_t file)
|
get_new_block (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
register ulg b; /* bit buffer */
|
register ulg b; /* bit buffer */
|
||||||
register unsigned k; /* number of bits in bit buffer */
|
register unsigned k; /* number of bits in bit buffer */
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* make local bit buffer */
|
/* make local bit buffer */
|
||||||
b = gzio->bb;
|
b = gzio->bb;
|
||||||
|
@ -1005,13 +1024,13 @@ get_new_block (grub_file_t file)
|
||||||
switch (gzio->block_type)
|
switch (gzio->block_type)
|
||||||
{
|
{
|
||||||
case INFLATE_STORED:
|
case INFLATE_STORED:
|
||||||
init_stored_block (file);
|
init_stored_block (gzio);
|
||||||
break;
|
break;
|
||||||
case INFLATE_FIXED:
|
case INFLATE_FIXED:
|
||||||
init_fixed_block (file);
|
init_fixed_block (gzio);
|
||||||
break;
|
break;
|
||||||
case INFLATE_DYNAMIC:
|
case INFLATE_DYNAMIC:
|
||||||
init_dynamic_block (file);
|
init_dynamic_block (gzio);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1020,10 +1039,8 @@ get_new_block (grub_file_t file)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
inflate_window (grub_file_t file)
|
inflate_window (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
/* initialize window */
|
/* initialize window */
|
||||||
gzio->wp = 0;
|
gzio->wp = 0;
|
||||||
|
|
||||||
|
@ -1038,7 +1055,7 @@ inflate_window (grub_file_t file)
|
||||||
if (gzio->last_block)
|
if (gzio->last_block)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
get_new_block (file);
|
get_new_block (gzio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gzio->block_type > INFLATE_DYNAMIC)
|
if (gzio->block_type > INFLATE_DYNAMIC)
|
||||||
|
@ -1061,7 +1078,7 @@ inflate_window (grub_file_t file)
|
||||||
|
|
||||||
while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
|
while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
gzio->slide[w++] = get_byte (file);
|
gzio->slide[w++] = get_byte (gzio);
|
||||||
gzio->block_len--;
|
gzio->block_len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,7 +1091,7 @@ inflate_window (grub_file_t file)
|
||||||
* Expand other kind of block.
|
* Expand other kind of block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (inflate_codes_in_window (file))
|
if (inflate_codes_in_window (gzio))
|
||||||
{
|
{
|
||||||
huft_free (gzio->tl);
|
huft_free (gzio->tl);
|
||||||
huft_free (gzio->td);
|
huft_free (gzio->td);
|
||||||
|
@ -1090,12 +1107,10 @@ inflate_window (grub_file_t file)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
initialize_tables (grub_file_t file)
|
initialize_tables (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
|
|
||||||
gzio->saved_offset = 0;
|
gzio->saved_offset = 0;
|
||||||
grub_file_seek (gzio->file, gzio->data_offset);
|
gzio_seek (gzio, gzio->data_offset);
|
||||||
|
|
||||||
/* Initialize the bit buffer. */
|
/* Initialize the bit buffer. */
|
||||||
gzio->bk = 0;
|
gzio->bk = 0;
|
||||||
|
@ -1140,7 +1155,7 @@ grub_gzio_open (grub_file_t io)
|
||||||
file->fs = &grub_gzio_fs;
|
file->fs = &grub_gzio_fs;
|
||||||
file->not_easily_seekable = 1;
|
file->not_easily_seekable = 1;
|
||||||
|
|
||||||
if (! test_header (file))
|
if (! test_gzip_header (file))
|
||||||
{
|
{
|
||||||
grub_free (gzio);
|
grub_free (gzio);
|
||||||
grub_free (file);
|
grub_free (file);
|
||||||
|
@ -1156,16 +1171,49 @@ grub_gzio_open (grub_file_t io)
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_zlib_header (grub_gzio_t gzio)
|
||||||
|
{
|
||||||
|
grub_uint8_t cmf, flg;
|
||||||
|
|
||||||
|
cmf = get_byte (gzio);
|
||||||
|
flg = get_byte (gzio);
|
||||||
|
|
||||||
|
/* Check that compression method is DEFLATE. */
|
||||||
|
if ((cmf & 0xf) != DEFLATED)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmf * 256 + flg) % 31)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dictionary isn't supported. */
|
||||||
|
if (flg & 0x20)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gzio->data_offset = 2;
|
||||||
|
initialize_tables (gzio);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
|
grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset,
|
||||||
|
char *buf, grub_size_t len)
|
||||||
{
|
{
|
||||||
grub_ssize_t ret = 0;
|
grub_ssize_t ret = 0;
|
||||||
grub_gzio_t gzio = file->data;
|
|
||||||
grub_off_t offset;
|
|
||||||
|
|
||||||
/* Do we reset decompression to the beginning of the file? */
|
/* Do we reset decompression to the beginning of the file? */
|
||||||
if (gzio->saved_offset > file->offset + WSIZE)
|
if (gzio->saved_offset > offset + WSIZE)
|
||||||
initialize_tables (file);
|
initialize_tables (gzio);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This loop operates upon uncompressed data only. The only
|
* This loop operates upon uncompressed data only. The only
|
||||||
|
@ -1173,15 +1221,13 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
* window is within the range of data it needs.
|
* window is within the range of data it needs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
offset = file->offset;
|
|
||||||
|
|
||||||
while (len > 0 && grub_errno == GRUB_ERR_NONE)
|
while (len > 0 && grub_errno == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
register grub_size_t size;
|
register grub_size_t size;
|
||||||
register char *srcaddr;
|
register char *srcaddr;
|
||||||
|
|
||||||
while (offset >= gzio->saved_offset)
|
while (offset >= gzio->saved_offset)
|
||||||
inflate_window (file);
|
inflate_window (gzio);
|
||||||
|
|
||||||
srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide);
|
srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide);
|
||||||
size = gzio->saved_offset - offset;
|
size = gzio->saved_offset - offset;
|
||||||
|
@ -1202,6 +1248,12 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_ssize_t
|
||||||
|
grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
|
{
|
||||||
|
return grub_gzio_read_real (file->data, file->offset, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
/* Release everything, including the underlying file object. */
|
/* Release everything, including the underlying file object. */
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_gzio_close (grub_file_t file)
|
grub_gzio_close (grub_file_t file)
|
||||||
|
@ -1219,6 +1271,33 @@ grub_gzio_close (grub_file_t file)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_ssize_t
|
||||||
|
grub_zlib_decompress (char *inbuf, grub_size_t insize, 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->mem_input = (grub_uint8_t *) inbuf;
|
||||||
|
gzio->mem_input_size = insize;
|
||||||
|
gzio->mem_input_off = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct grub_fs grub_gzio_fs =
|
static struct grub_fs grub_gzio_fs =
|
||||||
|
|
|
@ -105,14 +105,19 @@ xgetcwd (void)
|
||||||
can't deal with the multiple-device case yet, but in the meantime, we can
|
can't deal with the multiple-device case yet, but in the meantime, we can
|
||||||
at least cope with the single-device case by scanning
|
at least cope with the single-device case by scanning
|
||||||
/proc/self/mountinfo. */
|
/proc/self/mountinfo. */
|
||||||
static char *
|
char *
|
||||||
find_root_device_from_mountinfo (const char *dir)
|
grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
|
|
||||||
|
if (! *dir)
|
||||||
|
dir = "/";
|
||||||
|
if (relroot)
|
||||||
|
*relroot = NULL;
|
||||||
|
|
||||||
fp = fopen ("/proc/self/mountinfo", "r");
|
fp = fopen ("/proc/self/mountinfo", "r");
|
||||||
if (! fp)
|
if (! fp)
|
||||||
return NULL; /* fall through to other methods */
|
return NULL; /* fall through to other methods */
|
||||||
|
@ -126,16 +131,12 @@ find_root_device_from_mountinfo (const char *dir)
|
||||||
size_t enc_path_len;
|
size_t enc_path_len;
|
||||||
const char *sep;
|
const char *sep;
|
||||||
char fstype[PATH_MAX], device[PATH_MAX];
|
char fstype[PATH_MAX], device[PATH_MAX];
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||||
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
||||||
&count) < 6)
|
&count) < 6)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp (enc_root, "/") != 0)
|
|
||||||
continue; /* only a subtree is mounted */
|
|
||||||
|
|
||||||
enc_path_len = strlen (enc_path);
|
enc_path_len = strlen (enc_path);
|
||||||
/* Check that enc_path is a prefix of dir. The prefix must either be
|
/* Check that enc_path is a prefix of dir. The prefix must either be
|
||||||
the entire string, or end with a slash, or be immediately followed
|
the entire string, or end with a slash, or be immediately followed
|
||||||
|
@ -153,9 +154,6 @@ find_root_device_from_mountinfo (const char *dir)
|
||||||
free (ret);
|
free (ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
|
|
||||||
if (major != 0)
|
|
||||||
continue; /* not a virtual device */
|
|
||||||
|
|
||||||
sep = strstr (buf + count, " - ");
|
sep = strstr (buf + count, " - ");
|
||||||
if (!sep)
|
if (!sep)
|
||||||
continue;
|
continue;
|
||||||
|
@ -164,13 +162,9 @@ find_root_device_from_mountinfo (const char *dir)
|
||||||
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (stat (device, &st) < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!S_ISBLK (st.st_mode))
|
|
||||||
continue; /* not a block device */
|
|
||||||
|
|
||||||
ret = strdup (device);
|
ret = strdup (device);
|
||||||
|
if (relroot)
|
||||||
|
*relroot = strdup (enc_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (buf);
|
free (buf);
|
||||||
|
@ -479,7 +473,7 @@ grub_find_device (const char *path, dev_t dev)
|
||||||
char *
|
char *
|
||||||
grub_guess_root_device (const char *dir)
|
grub_guess_root_device (const char *dir)
|
||||||
{
|
{
|
||||||
char *os_dev;
|
char *os_dev = NULL;
|
||||||
#ifdef __GNU__
|
#ifdef __GNU__
|
||||||
file_t file;
|
file_t file;
|
||||||
mach_port_t *ports;
|
mach_port_t *ports;
|
||||||
|
@ -538,30 +532,42 @@ grub_guess_root_device (const char *dir)
|
||||||
mach_port_deallocate (mach_task_self (), file);
|
mach_port_deallocate (mach_task_self (), file);
|
||||||
#else /* !__GNU__ */
|
#else /* !__GNU__ */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
dev_t dev;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
os_dev = find_root_device_from_mountinfo (dir);
|
if (!os_dev)
|
||||||
if (os_dev)
|
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
|
||||||
return os_dev;
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||||
os_dev = find_root_device_from_libzfs (dir);
|
if (!os_dev)
|
||||||
if (os_dev)
|
os_dev = find_root_device_from_libzfs (dir);
|
||||||
return os_dev;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (stat (dir, &st) < 0)
|
if (os_dev)
|
||||||
grub_util_error ("cannot stat `%s'", dir);
|
{
|
||||||
|
if (stat (os_dev, &st) >= 0)
|
||||||
|
dev = st.st_rdev;
|
||||||
|
else
|
||||||
|
grub_util_error ("cannot stat `%s'", os_dev);
|
||||||
|
free (os_dev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (stat (dir, &st) >= 0)
|
||||||
|
dev = st.st_dev;
|
||||||
|
else
|
||||||
|
grub_util_error ("cannot stat `%s'", dir);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
/* Cygwin specific function. */
|
/* Cygwin specific function. */
|
||||||
os_dev = grub_find_device (dir, st.st_dev);
|
os_dev = grub_find_device (dir, dev);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* This might be truly slow, but is there any better way? */
|
/* This might be truly slow, but is there any better way? */
|
||||||
os_dev = grub_find_device ("/dev", st.st_dev);
|
os_dev = grub_find_device ("/dev", dev);
|
||||||
#endif
|
#endif
|
||||||
#endif /* !__GNU__ */
|
#endif /* !__GNU__ */
|
||||||
|
|
||||||
|
|
|
@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
{
|
{
|
||||||
free (buf);
|
free (buf);
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
char *bind;
|
||||||
|
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||||
|
if (bind && bind[0] && bind[1])
|
||||||
|
{
|
||||||
|
buf3 = bind;
|
||||||
|
goto parsedir;
|
||||||
|
}
|
||||||
|
grub_free (bind);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
free (buf2);
|
free (buf2);
|
||||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||||
if (poolfs)
|
if (poolfs)
|
||||||
|
@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
}
|
}
|
||||||
free (buf);
|
free (buf);
|
||||||
buf3 = xstrdup (buf2 + offset);
|
buf3 = xstrdup (buf2 + offset);
|
||||||
|
buf2[offset] = 0;
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
char *bind;
|
||||||
|
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||||
|
if (bind && bind[0] && bind[1])
|
||||||
|
{
|
||||||
|
char *temp = buf3;
|
||||||
|
buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
|
||||||
|
grub_free (temp);
|
||||||
|
}
|
||||||
|
grub_free (bind);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
free (buf2);
|
free (buf2);
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
|
@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
parsedir:
|
||||||
/* Remove trailing slashes, return empty string if root directory. */
|
/* Remove trailing slashes, return empty string if root directory. */
|
||||||
len = strlen (buf3);
|
len = strlen (buf3);
|
||||||
while (len > 0 && buf3[len - 1] == '/')
|
while (len > 0 && buf3[len - 1] == '/')
|
||||||
|
|
75
grub-core/lib/crc.c
Normal file
75
grub-core/lib/crc.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* crc.c - crc function */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/lib/crc.h>
|
||||||
|
|
||||||
|
static grub_uint32_t crc32c_table [256];
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_crc32c_table (void)
|
||||||
|
{
|
||||||
|
auto grub_uint32_t reflect (grub_uint32_t ref, int len);
|
||||||
|
grub_uint32_t reflect (grub_uint32_t ref, int len)
|
||||||
|
{
|
||||||
|
grub_uint32_t result = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i <= len; i++)
|
||||||
|
{
|
||||||
|
if (ref & 1)
|
||||||
|
result |= 1 << (len - i);
|
||||||
|
ref >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_uint32_t polynomial = 0x1edc6f41;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for(i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
crc32c_table[i] = reflect(i, 8) << 24;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
crc32c_table[i] = (crc32c_table[i] << 1) ^
|
||||||
|
(crc32c_table[i] & (1 << 31) ? polynomial : 0);
|
||||||
|
crc32c_table[i] = reflect(crc32c_table[i], 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_uint32_t
|
||||||
|
grub_getcrc32c (grub_uint32_t crc, const void *buf, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const grub_uint8_t *data = buf;
|
||||||
|
|
||||||
|
if (! crc32c_table[1])
|
||||||
|
init_crc32c_table ();
|
||||||
|
|
||||||
|
crc^= 0xffffffff;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
crc = (crc >> 8) ^ crc32c_table[(crc & 0xFF) ^ *data];
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc ^ 0xffffffff;
|
||||||
|
}
|
26
include/grub/deflate.h
Normal file
26
include/grub/deflate.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_DEFLATE_HEADER
|
||||||
|
#define GRUB_DEFLATE_HEADER 1
|
||||||
|
|
||||||
|
grub_ssize_t
|
||||||
|
grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
|
||||||
|
char *outbuf, grub_size_t outsize);
|
||||||
|
|
||||||
|
#endif
|
|
@ -78,4 +78,6 @@ extern char * canonicalize_file_name (const char *path);
|
||||||
int grub_device_mapper_supported (void);
|
int grub_device_mapper_supported (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot);
|
||||||
|
|
||||||
#endif /* GRUB_EMU_MISC_H */
|
#endif /* GRUB_EMU_MISC_H */
|
||||||
|
|
25
include/grub/lib/crc.h
Normal file
25
include/grub/lib/crc.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* crc.h - prototypes for crc */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_CRC_H
|
||||||
|
#define GRUB_CRC_H 1
|
||||||
|
|
||||||
|
grub_uint32_t grub_getcrc32c (grub_uint32_t crc, const void *buf, int size);
|
||||||
|
|
||||||
|
#endif /* ! GRUB_CRC_H */
|
Loading…
Reference in a new issue