From: Michael Chang <mch...@suse.com>

Signed-off-by: Michael Chang <mch...@suse.com>
Signed-off-by: Robbie Harwood <rharw...@redhat.com>
---
 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 14e38a4df..d47f9ab03 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1335,6 +1335,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)
     {
@@ -1365,11 +1366,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;
@@ -1966,24 +1970,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
     {
@@ -1994,15 +2013,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)
        {
@@ -2013,7 +2040,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] == '.')
@@ -2044,8 +2073,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;
        }
 
@@ -2114,7 +2144,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;
@@ -2164,14 +2196,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
                {
@@ -2922,6 +2966,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)
-- 
2.46.2


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to