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
|
@ -105,14 +105,19 @@ xgetcwd (void)
|
|||
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
|
||||
/proc/self/mountinfo. */
|
||||
static char *
|
||||
find_root_device_from_mountinfo (const char *dir)
|
||||
char *
|
||||
grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
char *ret = NULL;
|
||||
|
||||
if (! *dir)
|
||||
dir = "/";
|
||||
if (relroot)
|
||||
*relroot = NULL;
|
||||
|
||||
fp = fopen ("/proc/self/mountinfo", "r");
|
||||
if (! fp)
|
||||
return NULL; /* fall through to other methods */
|
||||
|
@ -126,16 +131,12 @@ find_root_device_from_mountinfo (const char *dir)
|
|||
size_t enc_path_len;
|
||||
const char *sep;
|
||||
char fstype[PATH_MAX], device[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
||||
&count) < 6)
|
||||
continue;
|
||||
|
||||
if (strcmp (enc_root, "/") != 0)
|
||||
continue; /* only a subtree is mounted */
|
||||
|
||||
enc_path_len = strlen (enc_path);
|
||||
/* 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
|
||||
|
@ -153,9 +154,6 @@ find_root_device_from_mountinfo (const char *dir)
|
|||
free (ret);
|
||||
ret = NULL;
|
||||
|
||||
if (major != 0)
|
||||
continue; /* not a virtual device */
|
||||
|
||||
sep = strstr (buf + count, " - ");
|
||||
if (!sep)
|
||||
continue;
|
||||
|
@ -164,13 +162,9 @@ find_root_device_from_mountinfo (const char *dir)
|
|||
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
||||
continue;
|
||||
|
||||
if (stat (device, &st) < 0)
|
||||
continue;
|
||||
|
||||
if (!S_ISBLK (st.st_mode))
|
||||
continue; /* not a block device */
|
||||
|
||||
ret = strdup (device);
|
||||
if (relroot)
|
||||
*relroot = strdup (enc_root);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
|
@ -479,7 +473,7 @@ grub_find_device (const char *path, dev_t dev)
|
|||
char *
|
||||
grub_guess_root_device (const char *dir)
|
||||
{
|
||||
char *os_dev;
|
||||
char *os_dev = NULL;
|
||||
#ifdef __GNU__
|
||||
file_t file;
|
||||
mach_port_t *ports;
|
||||
|
@ -538,30 +532,42 @@ grub_guess_root_device (const char *dir)
|
|||
mach_port_deallocate (mach_task_self (), file);
|
||||
#else /* !__GNU__ */
|
||||
struct stat st;
|
||||
dev_t dev;
|
||||
|
||||
#ifdef __linux__
|
||||
os_dev = find_root_device_from_mountinfo (dir);
|
||||
if (os_dev)
|
||||
return os_dev;
|
||||
if (!os_dev)
|
||||
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
os_dev = find_root_device_from_libzfs (dir);
|
||||
if (os_dev)
|
||||
return os_dev;
|
||||
if (!os_dev)
|
||||
os_dev = find_root_device_from_libzfs (dir);
|
||||
#endif
|
||||
|
||||
if (stat (dir, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", dir);
|
||||
if (os_dev)
|
||||
{
|
||||
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__
|
||||
/* Cygwin specific function. */
|
||||
os_dev = grub_find_device (dir, st.st_dev);
|
||||
os_dev = grub_find_device (dir, dev);
|
||||
|
||||
#else
|
||||
|
||||
/* 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 /* !__GNU__ */
|
||||
|
||||
|
|
|
@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
if (offset == 0)
|
||||
{
|
||||
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);
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (poolfs)
|
||||
|
@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
}
|
||||
free (buf);
|
||||
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);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
}
|
||||
#endif
|
||||
|
||||
parsedir:
|
||||
/* Remove trailing slashes, return empty string if root directory. */
|
||||
len = strlen (buf3);
|
||||
while (len > 0 && buf3[len - 1] == '/')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue