Skip to content

Commit

Permalink
btrfs: use libbtrfsutil for get/set default subvolume
Browse files Browse the repository at this point in the history
libbtrfsutil provides it's own error enum for libbtrfsutil functions and
as we no longer parse output this introduces a BD_BTRFS_ERROR_NOT_FOUND
error type. As the mount point not being found is the most likely
failure scenario.
  • Loading branch information
jelly committed Jan 25, 2024
1 parent 7cadfa1 commit 8ac2504
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 49 deletions.
59 changes: 12 additions & 47 deletions src/plugins/btrfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <unistd.h>
#include <blockdev/utils.h>
#include <bs_size.h>
#include <btrfsutil.h>

#include "btrfs.h"
#include "check_deps.h"
Expand Down Expand Up @@ -454,48 +455,14 @@ gboolean bd_btrfs_delete_subvolume (const gchar *mountpoint, const gchar *name,
* Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_QUERY
*/
guint64 bd_btrfs_get_default_subvolume_id (const gchar *mountpoint, GError **error) {
GRegex *regex = NULL;
GMatchInfo *match_info = NULL;
gboolean success = FALSE;
gchar *output = NULL;
gchar *match = NULL;
enum btrfs_util_error err;
guint64 ret = 0;
const gchar *argv[5] = {"btrfs", "subvol", "get-default", mountpoint, NULL};

if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) ||
!check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error))
return 0;

regex = g_regex_new ("ID (\\d+) .*", 0, 0, error);
if (!regex) {
bd_utils_log_format (BD_UTILS_LOG_WARNING, "Failed to create new GRegex");
/* error is already populated */
return 0;
}

success = bd_utils_exec_and_capture_output (argv, NULL, &output, error);
if (!success) {
g_regex_unref (regex);
return 0;
}

success = g_regex_match (regex, output, 0, &match_info);
if (!success) {
g_set_error (error, BD_BTRFS_ERROR, BD_BTRFS_ERROR_PARSE, "Failed to parse subvolume's ID");
g_regex_unref (regex);
g_match_info_free (match_info);
g_free (output);
return 0;
err = btrfs_util_get_default_subvolume (mountpoint, &ret);
if (err) {
g_set_error (error, BD_BTRFS_ERROR, BD_BTRFS_ERROR_NOT_FOUND, "%s: %m", btrfs_util_strerror (err));
}

match = g_match_info_fetch (match_info, 1);
ret = g_ascii_strtoull (match, NULL, 0);

g_free (match);
g_match_info_free (match_info);
g_regex_unref (regex);
g_free (output);

return ret;
}

Expand All @@ -512,17 +479,15 @@ guint64 bd_btrfs_get_default_subvolume_id (const gchar *mountpoint, GError **err
*
* Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_MODIFY
*/
gboolean bd_btrfs_set_default_subvolume (const gchar *mountpoint, guint64 subvol_id, const BDExtraArg **extra, GError **error) {
const gchar *argv[6] = {"btrfs", "subvol", "set-default", NULL, mountpoint, NULL};
gboolean bd_btrfs_set_default_subvolume (const gchar *mountpoint, guint64 subvol_id, G_GNUC_UNUSED const BDExtraArg **extra, GError **error) {
enum btrfs_util_error err;
gboolean ret = FALSE;

if (!check_deps (&avail_deps, DEPS_BTRFS_MASK, deps, DEPS_LAST, &deps_check_lock, error) ||
!check_module_deps (&avail_module_deps, MODULE_DEPS_BTRFS_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error))
return FALSE;

argv[3] = g_strdup_printf ("%"G_GUINT64_FORMAT, subvol_id);
ret = bd_utils_exec_and_report_error (argv, extra, error);
g_free ((gchar *) argv[3]);
err = btrfs_util_set_default_subvolume (mountpoint, subvol_id);
if (err)
g_set_error (error, BD_BTRFS_ERROR, BD_BTRFS_ERROR_NOT_FOUND, "%s: %m", btrfs_util_strerror (err));
else
ret = TRUE;

return ret;
}
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/btrfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ typedef enum {
BD_BTRFS_ERROR_TECH_UNAVAIL,
BD_BTRFS_ERROR_DEVICE,
BD_BTRFS_ERROR_PARSE,
BD_BTRFS_ERROR_NOT_FOUND,
} BDBtrfsError;

typedef struct BDBtrfsDeviceInfo {
Expand Down Expand Up @@ -79,7 +80,7 @@ gboolean bd_btrfs_remove_device (const gchar *mountpoint, const gchar *device, c
gboolean bd_btrfs_create_subvolume (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error);
gboolean bd_btrfs_delete_subvolume (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error);
guint64 bd_btrfs_get_default_subvolume_id (const gchar *mountpoint, GError **error);
gboolean bd_btrfs_set_default_subvolume (const gchar *mountpoint, guint64 subvol_id, const BDExtraArg **extra, GError **error);
gboolean bd_btrfs_set_default_subvolume (const gchar *mountpoint, guint64 subvol_id, G_GNUC_UNUSED const BDExtraArg **extra, GError **error);
gboolean bd_btrfs_create_snapshot (const gchar *source, const gchar *dest, gboolean ro, const BDExtraArg **extra, GError **error);
BDBtrfsDeviceInfo** bd_btrfs_list_devices (const gchar *device, GError **error);
BDBtrfsSubvolumeInfo** bd_btrfs_list_subvolumes (const gchar *mountpoint, gboolean snapshots_only, GError **error);
Expand Down
6 changes: 5 additions & 1 deletion tests/btrfs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def test_get_default_subvolume_id(self):
self.assertTrue(succ)

# not mounted yet, should fail
with self.assertRaisesRegex(GLib.GError, r".*(can't|cannot) access.*"):
with self.assertRaisesRegex(GLib.GError, r".*Could not open: No such file or directory.*"):
ret = BlockDev.btrfs_get_default_subvolume_id(TEST_MNT)

mount(self.loop_dev, TEST_MNT)
Expand All @@ -292,6 +292,10 @@ def test_set_default_subvolume(self):
succ = BlockDev.btrfs_create_volume([self.loop_dev], "myShinyBtrfs", None, None, None)
self.assertTrue(succ)

# not mounted yet, should fail
with self.assertRaisesRegex(GLib.GError, r".*Could not open: No such file or directory.*"):
ret = BlockDev.btrfs_get_default_subvolume_id(TEST_MNT)

mount(self.loop_dev, TEST_MNT)

ret = BlockDev.btrfs_get_default_subvolume_id(TEST_MNT)
Expand Down

0 comments on commit 8ac2504

Please sign in to comment.