254 lines
6.0 KiB
Diff
254 lines
6.0 KiB
Diff
v1:
|
|
References: bsc#1063443
|
|
|
|
v2:
|
|
References: bsc#1106381
|
|
Fix outputting invalid btrfs subvol path on non btrfs filesystem due to bogus
|
|
return code handling.
|
|
|
|
--- a/grub-core/fs/btrfs.c
|
|
+++ b/grub-core/fs/btrfs.c
|
|
@@ -3260,8 +3260,7 @@
|
|
}
|
|
|
|
static grub_err_t
|
|
-grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt,
|
|
- int argc, char **argv)
|
|
+grub_btrfs_get_default_subvol (const char *name, grub_uint64_t *ret_subvolid, char **ret_subvol)
|
|
{
|
|
char *devname;
|
|
grub_device_t dev;
|
|
@@ -3270,21 +3269,8 @@
|
|
grub_uint64_t id;
|
|
char *subvol = NULL;
|
|
grub_uint64_t subvolid = 0;
|
|
- char *varname = NULL;
|
|
- char *output = NULL;
|
|
- int path_only = ctxt->state[1].set;
|
|
- int num_only = ctxt->state[2].set;
|
|
-
|
|
- if (ctxt->state[0].set)
|
|
- varname = ctxt->state[0].arg;
|
|
-
|
|
- if (argc < 1)
|
|
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
|
-
|
|
- devname = grub_file_get_device_name(argv[0]);
|
|
- if (!devname)
|
|
- return grub_errno;
|
|
|
|
+ devname = grub_file_get_device_name(name);
|
|
dev = grub_device_open (devname);
|
|
grub_free (devname);
|
|
if (!dev)
|
|
@@ -3295,8 +3281,7 @@
|
|
{
|
|
grub_device_close (dev);
|
|
grub_dprintf ("btrfs", "failed to open fs\n");
|
|
- grub_errno = GRUB_ERR_NONE;
|
|
- return 0;
|
|
+ return grub_errno;
|
|
}
|
|
|
|
err = grub_btrfs_get_default_subvolume_id (data, &subvolid);
|
|
@@ -3325,12 +3310,47 @@
|
|
return err;
|
|
}
|
|
|
|
- if (subvol)
|
|
- grub_free (subvol);
|
|
+ grub_free (subvol);
|
|
subvol = path_out;
|
|
id = parent_id;
|
|
}
|
|
|
|
+ if (ret_subvolid)
|
|
+ *ret_subvolid = subvolid;
|
|
+ if (ret_subvol)
|
|
+ *ret_subvol = subvol;
|
|
+
|
|
+ grub_btrfs_unmount (data);
|
|
+ grub_device_close (dev);
|
|
+
|
|
+ return GRUB_ERR_NONE;
|
|
+}
|
|
+
|
|
+static grub_err_t
|
|
+grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt,
|
|
+ int argc, char **argv)
|
|
+{
|
|
+ grub_err_t err;
|
|
+ char *subvol = NULL;
|
|
+ grub_uint64_t subvolid = 0;
|
|
+ char *varname = NULL;
|
|
+ char *output = NULL;
|
|
+ int path_only = ctxt->state[1].set;
|
|
+ int num_only = ctxt->state[2].set;
|
|
+
|
|
+ if (ctxt->state[0].set)
|
|
+ varname = ctxt->state[0].arg;
|
|
+
|
|
+ if (argc < 1)
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
|
+
|
|
+ if ((err = grub_btrfs_get_default_subvol (argv[0], &subvolid, &subvol)) != GRUB_ERR_NONE)
|
|
+ {
|
|
+ if (err == GRUB_ERR_BAD_FS)
|
|
+ err = grub_errno = GRUB_ERR_NONE;
|
|
+ return err;
|
|
+ }
|
|
+
|
|
if (num_only && path_only)
|
|
output = grub_xasprintf ("%"PRIuGRUB_UINT64_T" /%s", subvolid, subvol);
|
|
else if (num_only)
|
|
@@ -3346,9 +3366,6 @@
|
|
grub_free (output);
|
|
grub_free (subvol);
|
|
|
|
- grub_btrfs_unmount (data);
|
|
- grub_device_close (dev);
|
|
-
|
|
return GRUB_ERR_NONE;
|
|
}
|
|
|
|
@@ -3427,6 +3444,122 @@
|
|
return "";
|
|
}
|
|
|
|
+
|
|
+static char *
|
|
+grub_btrfs_path_to_abs (const char *path)
|
|
+{
|
|
+ grub_err_t err;
|
|
+ char *device_name = NULL;
|
|
+ char *subvol = NULL;
|
|
+ const char *file_name;
|
|
+ char *ret;
|
|
+
|
|
+ if (!path)
|
|
+ return NULL;
|
|
+
|
|
+ if ((err = grub_btrfs_get_default_subvol (path, 0, &subvol)) != GRUB_ERR_NONE)
|
|
+ {
|
|
+ grub_errno = GRUB_ERR_NONE;
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (!subvol || *subvol == '\0')
|
|
+ return NULL;
|
|
+
|
|
+ file_name = (path[0] == '(') ? grub_strchr (path, ')') : NULL;
|
|
+ if (file_name)
|
|
+ file_name++;
|
|
+ else
|
|
+ file_name = path;
|
|
+ device_name = grub_file_get_device_name (path);
|
|
+ if (device_name)
|
|
+ ret = grub_xasprintf ("(%s)/%s%s", device_name, subvol, file_name);
|
|
+ else
|
|
+ ret = grub_xasprintf ("/%s%s", subvol, file_name);
|
|
+
|
|
+ grub_free (device_name);
|
|
+ grub_free (subvol);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static char *
|
|
+grub_btrfs_path_to_rel (const char *path)
|
|
+{
|
|
+ grub_err_t err;
|
|
+ char *subvol = NULL;
|
|
+ const char *file_name;
|
|
+
|
|
+ if (!path)
|
|
+ return NULL;
|
|
+
|
|
+ if ((err = grub_btrfs_get_default_subvol (path, 0, &subvol)) != GRUB_ERR_NONE)
|
|
+ {
|
|
+ grub_errno = GRUB_ERR_NONE;
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (!subvol || *subvol == '\0')
|
|
+ return NULL;
|
|
+
|
|
+ file_name = (path[0] == '(') ? grub_strchr (path, ')') : NULL;
|
|
+ if (file_name)
|
|
+ file_name++;
|
|
+ else
|
|
+ file_name = path;
|
|
+
|
|
+ if (*file_name == '/')
|
|
+ file_name++;
|
|
+
|
|
+ if (grub_strncmp (file_name, subvol, grub_strlen (subvol)) == 0)
|
|
+ {
|
|
+ char *device_name;
|
|
+ char *ret;
|
|
+
|
|
+ device_name = grub_file_get_device_name (path);
|
|
+ file_name += grub_strlen (subvol);
|
|
+ if (device_name)
|
|
+ ret = grub_xasprintf ("(%s)%s", device_name, file_name);
|
|
+ else
|
|
+ ret = grub_strdup (file_name);
|
|
+ grub_free (device_name);
|
|
+ grub_free (subvol);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ grub_free (subvol);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static char *
|
|
+relpath_set_env (struct grub_env_var *var,
|
|
+ const char *val)
|
|
+{
|
|
+ int new_val, old_val;
|
|
+ new_val = (val[0] == '1' || val[0] == 'y') ? 1 : 0;
|
|
+ old_val = (var->value[0] == '1' || var->value[0] == 'y') ? 1 : 0;
|
|
+
|
|
+ if (new_val != old_val)
|
|
+ {
|
|
+ const char **n;
|
|
+ char * (*path_to_xxx) (const char *);
|
|
+ const char *envname[] = {"config_file", "config_directory", NULL};
|
|
+
|
|
+ path_to_xxx = (new_val == 1) ? grub_btrfs_path_to_rel : grub_btrfs_path_to_abs;
|
|
+ for (n = envname; *n; n++)
|
|
+ {
|
|
+ char *ctmp = path_to_xxx (grub_env_get (*n));
|
|
+ if (ctmp)
|
|
+ {
|
|
+ grub_env_set (*n, ctmp);
|
|
+ grub_free (ctmp);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return grub_strdup (val);
|
|
+}
|
|
+
|
|
GRUB_MOD_INIT (btrfs)
|
|
{
|
|
grub_fs_register (&grub_btrfs_fs);
|
|
@@ -3450,6 +3583,8 @@
|
|
subvol_set_env);
|
|
grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env,
|
|
subvolid_set_env);
|
|
+ grub_register_variable_hook ("btrfs_relative_path", NULL,
|
|
+ relpath_set_env);
|
|
grub_env_export ("btrfs_subvol");
|
|
grub_env_export ("btrfs_subvolid");
|
|
grub_env_export ("btrfs_relative_path");
|
|
@@ -3459,6 +3594,7 @@
|
|
{
|
|
grub_register_variable_hook ("btrfs_subvol", NULL, NULL);
|
|
grub_register_variable_hook ("btrfs_subvolid", NULL, NULL);
|
|
+ grub_register_variable_hook ("btrfs_relative_path", NULL, NULL);
|
|
grub_unregister_command (cmd_info);
|
|
grub_unregister_extcmd (cmd_list_subvols);
|
|
grub_fs_unregister (&grub_btrfs_fs);
|