From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Thu, 21 Aug 2014 03:39:11 +0000 Subject: [PATCH] grub2-btrfs-03-follow_default Signed-off-by: Michael Chang Signed-off-by: Robbie Harwood --- grub-core/fs/btrfs.c | 107 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index ad1b56b716d..113c1f746c9 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1256,6 +1256,7 @@ grub_btrfs_mount (grub_device_t dev) { struct grub_btrfs_data *data; grub_err_t err; + const char *relpath = grub_env_get ("btrfs_relative_path"); if (!dev->disk) { @@ -1286,11 +1287,14 @@ grub_btrfs_mount (grub_device_t dev) data->devices_attached[0].dev = dev; data->devices_attached[0].id = data->sblock.this_device.device_id; - err = btrfs_handle_subvol (data); - if (err) + if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) { - grub_free (data); - return NULL; + err = btrfs_handle_subvol (data); + if (err) + { + grub_free (data); + return NULL; + } } return data; @@ -1855,24 +1859,39 @@ find_path (struct grub_btrfs_data *data, grub_size_t allocated = 0; struct grub_btrfs_dir_item *direl = NULL; struct grub_btrfs_key key_out; + int follow_default; const char *ctoken; grub_size_t ctokenlen; char *path_alloc = NULL; char *origpath = NULL; unsigned symlinks_max = 32; + const char *relpath = grub_env_get ("btrfs_relative_path"); + follow_default = 0; origpath = grub_strdup (path); if (!origpath) return grub_errno; - if (data->fs_tree) + if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) { - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->fs_tree; - /* This is a tree root, so everything starts at objectid 256 */ - key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; + if (data->fs_tree) + { + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->fs_tree; + /* This is a tree root, so everything starts at objectid 256 */ + key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + } + else + { + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->sblock.root_tree; + key->object_id = data->sblock.root_dir_objectid; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + follow_default = 1; + } } else { @@ -1883,15 +1902,23 @@ find_path (struct grub_btrfs_data *data, while (1) { - while (path[0] == '/') - path++; - if (!path[0]) - break; - slash = grub_strchr (path, '/'); - if (!slash) - slash = path + grub_strlen (path); - ctoken = path; - ctokenlen = slash - path; + if (!follow_default) + { + while (path[0] == '/') + path++; + if (!path[0]) + break; + slash = grub_strchr (path, '/'); + if (!slash) + slash = path + grub_strlen (path); + ctoken = path; + ctokenlen = slash - path; + } + else + { + ctoken = "default"; + ctokenlen = sizeof ("default") - 1; + } if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { @@ -1902,7 +1929,9 @@ find_path (struct grub_btrfs_data *data, if (ctokenlen == 1 && ctoken[0] == '.') { - path = slash; + if (!follow_default) + path = slash; + follow_default = 0; continue; } if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') @@ -1933,8 +1962,9 @@ find_path (struct grub_btrfs_data *data, *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; key->object_id = key_out.offset; - path = slash; - + if (!follow_default) + path = slash; + follow_default = 0; continue; } @@ -2003,7 +2033,9 @@ find_path (struct grub_btrfs_data *data, return err; } - path = slash; + if (!follow_default) + path = slash; + follow_default = 0; if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) { struct grub_btrfs_inode inode; @@ -2053,14 +2085,26 @@ find_path (struct grub_btrfs_data *data, path = path_alloc = tmp; if (path[0] == '/') { - if (data->fs_tree) + if (relpath && (relpath[0] == '1' || relpath[0] == 'y')) { - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->fs_tree; - /* This is a tree root, so everything starts at objectid 256 */ - key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; + if (data->fs_tree) + { + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->fs_tree; + /* This is a tree root, so everything starts at objectid 256 */ + key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + } + else + { + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->sblock.root_tree; + key->object_id = data->sblock.root_dir_objectid; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + follow_default = 1; + } } else { @@ -2716,6 +2760,7 @@ GRUB_MOD_INIT (btrfs) subvolid_set_env); grub_env_export ("btrfs_subvol"); grub_env_export ("btrfs_subvolid"); + grub_env_export ("btrfs_relative_path"); } GRUB_MOD_FINI (btrfs)