Make / in btrfs refer to real root, not the default volume.
Modify mkrelpath to work even if device is mounted with subvolid option.
This commit is contained in:
parent
11d81fc6d1
commit
82591fa6e7
6 changed files with 311 additions and 123 deletions
|
@ -1,4 +1,9 @@
|
||||||
2013-10-14 Andrey Borzenkov <arvidjaar@gmail.com>
|
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Make / in btrfs refer to real root, not the default volume.
|
||||||
|
Modify mkrelpath to work even if device is mounted with subvolid option.
|
||||||
|
|
||||||
|
2013-10-28 Andrey Borzenkov <arvidjaar@gmail.com>
|
||||||
|
|
||||||
* Makefile.util.def: Add grub-core/kern/disk_common.c to library
|
* Makefile.util.def: Add grub-core/kern/disk_common.c to library
|
||||||
extra_dist.
|
extra_dist.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* btrfs.c - B-tree file system. */
|
/* btrfs.c - B-tree file system. */
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
* Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <grub/deflate.h>
|
#include <grub/deflate.h>
|
||||||
#include <minilzo.h>
|
#include <minilzo.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/btrfs.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -106,24 +107,6 @@ struct grub_btrfs_data
|
||||||
struct grub_btrfs_extent_data *extent;
|
struct grub_btrfs_extent_data *extent;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_INODE_ITEM = 0x01,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_INODE_REF = 0x0c,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_DIR_ITEM = 0x54,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM = 0x6c,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8,
|
|
||||||
GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4
|
|
||||||
};
|
|
||||||
|
|
||||||
struct grub_btrfs_key
|
|
||||||
{
|
|
||||||
grub_uint64_t object_id;
|
|
||||||
grub_uint8_t type;
|
|
||||||
grub_uint64_t offset;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_btrfs_chunk_item
|
struct grub_btrfs_chunk_item
|
||||||
{
|
{
|
||||||
grub_uint64_t size;
|
grub_uint64_t size;
|
||||||
|
@ -188,13 +171,6 @@ struct grub_btrfs_leaf_descriptor
|
||||||
} *data;
|
} *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct grub_btrfs_root_item
|
|
||||||
{
|
|
||||||
grub_uint8_t dummy[0xb0];
|
|
||||||
grub_uint64_t tree;
|
|
||||||
grub_uint64_t inode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct grub_btrfs_time
|
struct grub_btrfs_time
|
||||||
{
|
{
|
||||||
grub_int64_t sec;
|
grub_int64_t sec;
|
||||||
|
@ -1196,6 +1172,40 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
return pos - pos0;
|
return pos - pos0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key,
|
||||||
|
grub_uint64_t *tree, grub_uint8_t *type)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
grub_disk_addr_t elemaddr;
|
||||||
|
grub_size_t elemsize;
|
||||||
|
struct grub_btrfs_key key_out, key_in;
|
||||||
|
struct grub_btrfs_root_item ri;
|
||||||
|
|
||||||
|
key_in.object_id = GRUB_BTRFS_ROOT_VOL_OBJECTID;
|
||||||
|
key_in.offset = 0;
|
||||||
|
key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM;
|
||||||
|
err = lower_bound (data, &key_in, &key_out,
|
||||||
|
data->sblock.root_tree,
|
||||||
|
&elemaddr, &elemsize, NULL, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (key_in.object_id != key_out.object_id
|
||||||
|
|| key_in.type != key_out.type
|
||||||
|
|| key_in.offset != key_out.offset)
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "no root");
|
||||||
|
err = grub_btrfs_read_logical (data, elemaddr, &ri,
|
||||||
|
sizeof (ri), 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
|
||||||
|
key->offset = 0;
|
||||||
|
key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
|
||||||
|
*tree = ri.tree;
|
||||||
|
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
find_path (struct grub_btrfs_data *data,
|
find_path (struct grub_btrfs_data *data,
|
||||||
const char *path, struct grub_btrfs_key *key,
|
const char *path, struct grub_btrfs_key *key,
|
||||||
|
@ -1208,26 +1218,21 @@ find_path (struct grub_btrfs_data *data,
|
||||||
grub_size_t allocated = 0;
|
grub_size_t allocated = 0;
|
||||||
struct grub_btrfs_dir_item *direl = NULL;
|
struct grub_btrfs_dir_item *direl = NULL;
|
||||||
struct grub_btrfs_key key_out;
|
struct grub_btrfs_key key_out;
|
||||||
int skip_default;
|
|
||||||
const char *ctoken;
|
const char *ctoken;
|
||||||
grub_size_t ctokenlen;
|
grub_size_t ctokenlen;
|
||||||
char *path_alloc = NULL;
|
char *path_alloc = NULL;
|
||||||
char *origpath = NULL;
|
char *origpath = NULL;
|
||||||
unsigned symlinks_max = 32;
|
unsigned symlinks_max = 32;
|
||||||
|
|
||||||
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
|
err = get_root (data, key, tree, type);
|
||||||
*tree = data->sblock.root_tree;
|
if (err)
|
||||||
key->object_id = data->sblock.root_dir_objectid;
|
return err;
|
||||||
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
|
|
||||||
key->offset = 0;
|
|
||||||
skip_default = 1;
|
|
||||||
origpath = grub_strdup (path);
|
origpath = grub_strdup (path);
|
||||||
if (!origpath)
|
if (!origpath)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
|
||||||
if (!skip_default)
|
|
||||||
{
|
{
|
||||||
while (path[0] == '/')
|
while (path[0] == '/')
|
||||||
path++;
|
path++;
|
||||||
|
@ -1238,12 +1243,6 @@ find_path (struct grub_btrfs_data *data,
|
||||||
slash = path + grub_strlen (path);
|
slash = path + grub_strlen (path);
|
||||||
ctoken = path;
|
ctoken = path;
|
||||||
ctokenlen = slash - path;
|
ctokenlen = slash - path;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctoken = "default";
|
|
||||||
ctokenlen = sizeof ("default") - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
|
if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
|
||||||
{
|
{
|
||||||
|
@ -1254,9 +1253,7 @@ find_path (struct grub_btrfs_data *data,
|
||||||
|
|
||||||
if (ctokenlen == 1 && ctoken[0] == '.')
|
if (ctokenlen == 1 && ctoken[0] == '.')
|
||||||
{
|
{
|
||||||
if (!skip_default)
|
|
||||||
path = slash;
|
path = slash;
|
||||||
skip_default = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.')
|
if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.')
|
||||||
|
@ -1287,9 +1284,7 @@ find_path (struct grub_btrfs_data *data,
|
||||||
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
|
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
|
||||||
key->object_id = key_out.offset;
|
key->object_id = key_out.offset;
|
||||||
|
|
||||||
if (!skip_default)
|
|
||||||
path = slash;
|
path = slash;
|
||||||
skip_default = 0;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1359,9 +1354,7 @@ find_path (struct grub_btrfs_data *data,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skip_default)
|
|
||||||
path = slash;
|
path = slash;
|
||||||
skip_default = 0;
|
|
||||||
if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK)
|
if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK)
|
||||||
{
|
{
|
||||||
struct grub_btrfs_inode inode;
|
struct grub_btrfs_inode inode;
|
||||||
|
@ -1411,12 +1404,9 @@ find_path (struct grub_btrfs_data *data,
|
||||||
path = path_alloc = tmp;
|
path = path_alloc = tmp;
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
{
|
{
|
||||||
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
|
err = get_root (data, key, tree, type);
|
||||||
*tree = data->sblock.root_tree;
|
if (err)
|
||||||
key->object_id = data->sblock.root_dir_objectid;
|
return err;
|
||||||
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
|
|
||||||
key->offset = 0;
|
|
||||||
skip_default = 1;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,15 +49,18 @@
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <btrfs/ioctl.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/raid/md_p.h>
|
#include <linux/raid/md_p.h>
|
||||||
#include <linux/raid/md_u.h>
|
#include <linux/raid/md_u.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/emu/exec.h>
|
#include <grub/emu/exec.h>
|
||||||
|
#include <grub/btrfs.h>
|
||||||
|
|
||||||
#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
|
#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Defines taken from btrfs/ioctl.h. */
|
/* Defines taken from btrfs/ioctl.h. */
|
||||||
|
|
||||||
struct btrfs_ioctl_dev_info_args
|
struct btrfs_ioctl_dev_info_args
|
||||||
|
@ -82,7 +85,7 @@ struct btrfs_ioctl_fs_info_args
|
||||||
struct btrfs_ioctl_dev_info_args)
|
struct btrfs_ioctl_dev_info_args)
|
||||||
#define BTRFS_IOC_FS_INFO _IOR(0x94, 31, \
|
#define BTRFS_IOC_FS_INFO _IOR(0x94, 31, \
|
||||||
struct btrfs_ioctl_fs_info_args)
|
struct btrfs_ioctl_fs_info_args)
|
||||||
|
#endif
|
||||||
static int
|
static int
|
||||||
grub_util_is_imsm (const char *os_dev);
|
grub_util_is_imsm (const char *os_dev);
|
||||||
|
|
||||||
|
@ -224,6 +227,117 @@ grub_find_root_devices_from_btrfs (const char *dir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_btrfs_fs_prefix (const char *mount_path)
|
||||||
|
{
|
||||||
|
struct btrfs_ioctl_ino_lookup_args args;
|
||||||
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
grub_uint64_t tree_id, inode_id;
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
fd = open (mount_path, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
memset (&args, 0, sizeof(args));
|
||||||
|
args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID;
|
||||||
|
|
||||||
|
if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
|
||||||
|
return NULL;
|
||||||
|
tree_id = args.treeid;
|
||||||
|
|
||||||
|
if (fstat (fd, &st) < 0)
|
||||||
|
return NULL;
|
||||||
|
inode_id = st.st_ino;
|
||||||
|
|
||||||
|
while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID
|
||||||
|
|| inode_id != GRUB_BTRFS_TREE_ROOT_OBJECTID)
|
||||||
|
{
|
||||||
|
grub_uint64_t *nid;
|
||||||
|
const char *name;
|
||||||
|
size_t namelen;
|
||||||
|
struct btrfs_ioctl_search_args sargs;
|
||||||
|
char *old;
|
||||||
|
|
||||||
|
memset (&sargs, 0, sizeof(sargs));
|
||||||
|
|
||||||
|
if (inode_id == GRUB_BTRFS_TREE_ROOT_OBJECTID)
|
||||||
|
{
|
||||||
|
struct grub_btrfs_root_backref *br;
|
||||||
|
|
||||||
|
sargs.key.tree_id = 1;
|
||||||
|
sargs.key.min_objectid = tree_id;
|
||||||
|
sargs.key.max_objectid = tree_id;
|
||||||
|
|
||||||
|
sargs.key.min_offset = 0;
|
||||||
|
sargs.key.max_offset = ~0ULL;
|
||||||
|
sargs.key.min_transid = 0;
|
||||||
|
sargs.key.max_transid = ~0ULL;
|
||||||
|
sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF;
|
||||||
|
sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF;
|
||||||
|
|
||||||
|
sargs.key.nr_items = 1;
|
||||||
|
|
||||||
|
if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (sargs.key.nr_items == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nid = (grub_uint64_t *) (sargs.buf + 16);
|
||||||
|
tree_id = *nid;
|
||||||
|
br = (struct grub_btrfs_root_backref *) (sargs.buf + 32);
|
||||||
|
inode_id = br->inode_id;
|
||||||
|
name = br->name;
|
||||||
|
namelen = br->n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct grub_btrfs_inode_ref *ir;
|
||||||
|
|
||||||
|
sargs.key.tree_id = tree_id;
|
||||||
|
sargs.key.min_objectid = inode_id;
|
||||||
|
sargs.key.max_objectid = inode_id;
|
||||||
|
|
||||||
|
sargs.key.min_offset = 0;
|
||||||
|
sargs.key.max_offset = ~0ULL;
|
||||||
|
sargs.key.min_transid = 0;
|
||||||
|
sargs.key.max_transid = ~0ULL;
|
||||||
|
sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_INODE_REF;
|
||||||
|
sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_INODE_REF;
|
||||||
|
|
||||||
|
if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (sargs.key.nr_items == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nid = (grub_uint64_t *) (sargs.buf + 16);
|
||||||
|
inode_id = *nid;
|
||||||
|
|
||||||
|
ir = (struct grub_btrfs_inode_ref *) (sargs.buf + 32);
|
||||||
|
name = ir->name;
|
||||||
|
namelen = ir->n;
|
||||||
|
}
|
||||||
|
old = ret;
|
||||||
|
ret = xmalloc (namelen + (old ? strlen (old) : 0) + 2);
|
||||||
|
ret[0] = '/';
|
||||||
|
memcpy (ret + 1, name, namelen);
|
||||||
|
if (old)
|
||||||
|
{
|
||||||
|
strcpy (ret + 1 + namelen, old);
|
||||||
|
free (old);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret[1+namelen] = '\0';
|
||||||
|
}
|
||||||
|
if (!ret)
|
||||||
|
return xstrdup ("/");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char **
|
char **
|
||||||
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
|
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
|
||||||
{
|
{
|
||||||
|
@ -332,6 +446,7 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
|
||||||
for (i = entry_len - 1; i >= 0; i--)
|
for (i = entry_len - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
char **ret = NULL;
|
char **ret = NULL;
|
||||||
|
char *fs_prefix = NULL;
|
||||||
if (!*entries[i].device)
|
if (!*entries[i].device)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -348,41 +463,48 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
|
||||||
if (relroot)
|
if (relroot)
|
||||||
{
|
{
|
||||||
if (!slash)
|
if (!slash)
|
||||||
*relroot = xasprintf ("/@%s", entries[i].enc_root);
|
fs_prefix = xasprintf ("/@%s", entries[i].enc_root);
|
||||||
else if (strchr (slash + 1, '@'))
|
else if (strchr (slash + 1, '@'))
|
||||||
*relroot = xasprintf ("/%s%s", slash + 1, entries[i].enc_root);
|
fs_prefix = xasprintf ("/%s%s", slash + 1, entries[i].enc_root);
|
||||||
else
|
else
|
||||||
*relroot = xasprintf ("/%s@%s", slash + 1, entries[i].enc_root);
|
fs_prefix = xasprintf ("/%s@%s", slash + 1,
|
||||||
|
entries[i].enc_root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (grub_strcmp (entries[i].fstype, "btrfs") == 0)
|
else if (grub_strcmp (entries[i].fstype, "btrfs") == 0)
|
||||||
{
|
{
|
||||||
ret = grub_find_root_devices_from_btrfs (dir);
|
ret = grub_find_root_devices_from_btrfs (dir);
|
||||||
if (relroot)
|
fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path);
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
*relroot = xmalloc (strlen (entries[i].enc_root) +
|
|
||||||
2 + strlen (dir));
|
|
||||||
ptr = grub_stpcpy (*relroot, entries[i].enc_root);
|
|
||||||
if (strlen (dir) > strlen (entries[i].enc_path))
|
|
||||||
{
|
|
||||||
while (ptr > *relroot && *(ptr - 1) == '/')
|
|
||||||
ptr--;
|
|
||||||
if (dir[strlen (entries[i].enc_path)] != '/')
|
|
||||||
*ptr++ = '/';
|
|
||||||
ptr = grub_stpcpy (ptr, dir + strlen (entries[i].enc_path));
|
|
||||||
}
|
|
||||||
*ptr = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
ret = xmalloc (2 * sizeof (ret[0]));
|
ret = xmalloc (2 * sizeof (ret[0]));
|
||||||
ret[0] = strdup (entries[i].device);
|
ret[0] = strdup (entries[i].device);
|
||||||
ret[1] = 0;
|
ret[1] = 0;
|
||||||
if (relroot)
|
|
||||||
*relroot = strdup (entries[i].enc_root);
|
|
||||||
}
|
}
|
||||||
|
if (!fs_prefix)
|
||||||
|
fs_prefix = entries[i].enc_root;
|
||||||
|
if (relroot)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
grub_size_t enc_root_len = strlen (fs_prefix);
|
||||||
|
grub_size_t enc_path_len = strlen (entries[i].enc_path);
|
||||||
|
grub_size_t dir_strlen = strlen (dir);
|
||||||
|
*relroot = xmalloc (enc_root_len +
|
||||||
|
2 + dir_strlen);
|
||||||
|
ptr = grub_stpcpy (*relroot, fs_prefix);
|
||||||
|
if (dir_strlen > enc_path_len)
|
||||||
|
{
|
||||||
|
while (ptr > *relroot && *(ptr - 1) == '/')
|
||||||
|
ptr--;
|
||||||
|
if (dir[enc_path_len] != '/')
|
||||||
|
*ptr++ = '/';
|
||||||
|
ptr = grub_stpcpy (ptr, dir + enc_path_len);
|
||||||
|
}
|
||||||
|
*ptr = 0;
|
||||||
|
}
|
||||||
|
if (fs_prefix != entries[i].enc_root)
|
||||||
|
free (fs_prefix);
|
||||||
free (buf);
|
free (buf);
|
||||||
free (entries);
|
free (entries);
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
|
@ -913,3 +1035,23 @@ grub_util_get_grub_dev_os (const char *os_dev)
|
||||||
|
|
||||||
return grub_dev;
|
return grub_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
grub_make_system_path_relative_to_its_root_os (const char *path)
|
||||||
|
{
|
||||||
|
char *bind = NULL;
|
||||||
|
grub_size_t len;
|
||||||
|
grub_free (grub_find_root_devices_from_mountinfo (path, &bind));
|
||||||
|
if (bind && bind[0])
|
||||||
|
{
|
||||||
|
len = strlen (bind);
|
||||||
|
while (len > 0 && bind[len - 1] == '/')
|
||||||
|
{
|
||||||
|
bind[len - 1] = '\0';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
return bind;
|
||||||
|
}
|
||||||
|
grub_free (bind);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -48,7 +48,13 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
grub_util_error (_("failed to get canonical path of `%s'"), path);
|
grub_util_error (_("failed to get canonical path of `%s'"), path);
|
||||||
|
|
||||||
/* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */
|
#ifdef __linux__
|
||||||
|
ret = grub_make_system_path_relative_to_its_root_os (p);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For ZFS sub-pool filesystems. */
|
||||||
#ifndef __HAIKU__
|
#ifndef __HAIKU__
|
||||||
{
|
{
|
||||||
char *dummy;
|
char *dummy;
|
||||||
|
@ -98,18 +104,6 @@ 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_devices_from_mountinfo (buf2, &bind));
|
|
||||||
if (bind && bind[0] && bind[1])
|
|
||||||
{
|
|
||||||
buf3 = bind;
|
|
||||||
goto parsedir;
|
|
||||||
}
|
|
||||||
grub_free (bind);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
free (buf2);
|
free (buf2);
|
||||||
if (poolfs)
|
if (poolfs)
|
||||||
return xasprintf ("/%s/@", poolfs);
|
return xasprintf ("/%s/@", poolfs);
|
||||||
|
@ -131,25 +125,9 @@ 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;
|
buf2[offset] = 0;
|
||||||
#ifdef __linux__
|
|
||||||
{
|
|
||||||
char *bind;
|
|
||||||
grub_free (grub_find_root_devices_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 __linux__
|
|
||||||
parsedir:
|
|
||||||
#endif
|
|
||||||
/* 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] == '/')
|
||||||
|
|
71
include/grub/btrfs.h
Normal file
71
include/grub/btrfs.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* btrfs.c - B-tree file system. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2010,2011,2012,2013 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_BTRFS_H
|
||||||
|
#define GRUB_BTRFS_H 1
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_INODE_ITEM = 0x01,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_INODE_REF = 0x0c,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_DIR_ITEM = 0x54,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM = 0x6c,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF = 0x90,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8,
|
||||||
|
GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GRUB_BTRFS_ROOT_VOL_OBJECTID = 5,
|
||||||
|
GRUB_BTRFS_TREE_ROOT_OBJECTID = 0x100,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_btrfs_root_item
|
||||||
|
{
|
||||||
|
grub_uint8_t dummy[0xb0];
|
||||||
|
grub_uint64_t tree;
|
||||||
|
grub_uint64_t inode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_btrfs_key
|
||||||
|
{
|
||||||
|
grub_uint64_t object_id;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint64_t offset;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
struct grub_btrfs_root_backref
|
||||||
|
{
|
||||||
|
grub_uint64_t inode_id;
|
||||||
|
grub_uint64_t seqnr;
|
||||||
|
grub_uint16_t n;
|
||||||
|
char name[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_btrfs_inode_ref
|
||||||
|
{
|
||||||
|
grub_uint64_t idxid;
|
||||||
|
grub_uint16_t n;
|
||||||
|
char name[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -36,6 +36,8 @@ void grub_util_pull_device (const char *osname);
|
||||||
char **grub_guess_root_devices (const char *dir);
|
char **grub_guess_root_devices (const char *dir);
|
||||||
int grub_util_get_dev_abstraction (const char *os_dev);
|
int grub_util_get_dev_abstraction (const char *os_dev);
|
||||||
char *grub_make_system_path_relative_to_its_root (const char *path);
|
char *grub_make_system_path_relative_to_its_root (const char *path);
|
||||||
|
char *
|
||||||
|
grub_make_system_path_relative_to_its_root_os (const char *path);
|
||||||
char *grub_util_get_grub_dev (const char *os_dev);
|
char *grub_util_get_grub_dev (const char *os_dev);
|
||||||
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
void grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out,
|
void grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out,
|
||||||
|
|
Loading…
Reference in a new issue