]> git.ipfire.org Git - people/stevee/ipfire-2.x.git/commitdiff
filesystem-functions.pl: Add functions to get snapshots/subvolumes
authorStefan Schantl <stefan.schantl@ipfire.org>
Sun, 5 May 2024 14:56:47 +0000 (16:56 +0200)
committerStefan Schantl <stefan.schantl@ipfire.org>
Sun, 5 May 2024 14:56:47 +0000 (16:56 +0200)
The btrfs_get_snapshots() and btrfs_get_subvolumes() functions are
designed to be used to get the desired details.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
config/cfgroot/filesystem-functions.pl

index d48cbe1f68a51b27729c6d78b532ed5b39e69c59..6b041bc177b1e59f6aded18e146a22092fb7a22d 100644 (file)
@@ -614,4 +614,94 @@ sub btrfs_subvolume_snapshot ($$$) {
        return;
 }
 
+#
+## Easy to use function to get all created snapshots of a given volume.
+##
+## It uses the filter_subvolume_list function to only provide snapshots and
+## returns the data in the same way as recieved.
+#
+sub btrfs_get_snapshots ($) {
+       my ($volume) = @_;
+
+       my %snapshots = &_filter_subvolume_list (
+               "volume" => $volume,
+               "type" => "snapshots"
+       );
+
+       return %snapshots;
+}
+
+#
+## Easy to use function to get the subvolumes of a given BTRFS volume.
+##
+## It also uses the filter_subvolume_list function only provide subvolumes
+## returns the data in the same way as recieved.
+#
+sub btrfs_get_subvolumes ($) {
+       my ($volume) = @_;
+
+       my %subvolumes = &_filter_subvolume_list (
+               "volume" => $volume,
+               "type" => "subvolumes"
+       );
+
+       return %subvolumes;
+}
+
+#
+## Private function to filter the output of btrfs_subvolume_list command.
+##
+## It can be used to return subvolumes or snapshots and will return them
+## as a hash with the format "ID" => "path".
+##
+## Example: "256" => "@root" (in case subvolumes should be dispalyed.
+##          "xxx" => "<name>" (in case snapshots are requested and at least one exist)
+#
+sub _filter_subvolume_list (%) {
+       my (%options) = @_;
+
+       # Hash to translate filter type into level number.
+       my %level = (
+               "subvolumes" => "5",
+               "snapshots" => "257"
+       );
+
+       # Assign options values.
+       my $volume = $options{"volume"} if ($options{"volume"});
+       my $type = $options{"type"} if ($options{"type"});
+       my $filter_level = $level{$type} if ($type);
+       
+       # Hash to store the filtered subvolumes.
+       my %subvolumes;
+
+       # Call btrfs_subvolume_list function to get a list of all known subvolumes and snapshots.
+       my @output = &btrfs_subvolume_list($volume);
+
+       # Loop through the output array of the btrfs subvolumes list command.
+       foreach my $line (@output) {
+               # Parse the line and assign humand readable values.
+               $line =~ /ID (.*) gen (.*) top level (.*) path (.*)/ || next;
+               my ($id, $gen, $level, $path) = ($1, $2, $3, $4);
+
+               # Skip current line if only a certain type is requested.
+               next if (($type) && ($level ne $filter_level));
+
+               # Check if snapshots are requested.
+               if ($type eq "snapshots") {
+                       # Split the returned path into pieces to only return the
+                       # name of the snapshot without subvolume details.
+                       my ($subvol, $name) = split("/", $path);
+
+                       # Assign the snapshot name as path.
+                       $path = $name;
+               }
+
+               # Assign the current element to the hash of subvolumes.
+               $subvolumes{$id} = $path;
+       }
+
+       # Return a hash reference.
+       return %subvolumes;
+}
+
 1;