Last active
July 15, 2017 23:37
-
-
Save vifon/7f6ad8f8c8171456f58c7b0ca93f66e0 to your computer and use it in GitHub Desktop.
lsblk fix for Linux 4.8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
=head1 Fix lsblk on Linux 4.8 | |
On Linux 4.8 the order of devices is screwed up. Let's sort it manually. | |
=cut | |
use warnings; | |
use strict; | |
use 5.010; | |
use utf8; | |
use open IO => ':encoding(UTF-8)'; | |
use open ':std' => ':encoding(UTF-8)'; | |
# Parse and load the lsblk tree into a nested hash. | |
sub parse_devices { | |
my (%args) = @_; | |
my @lines = @{ $args{lines} }; | |
my $prefix = $args{prefix} // 0; | |
my %device_trees = (); | |
# Parse each top-level node. We'll deal with the children later. | |
my $this_device = undef; | |
for (@lines) { | |
if (/^[^a-zA-Z]{$prefix}[a-zA-Z]/) { | |
# It's a new top-level node, let's initialize it. | |
$this_device = $_; | |
$device_trees{$this_device} = []; | |
} else { | |
# It's a child node, let's append it to its parent. | |
push @{ $device_trees{$this_device} }, $_; | |
} | |
} | |
# So far we have a single-level structure, a hash of arrays. We'd | |
# like to turn these arrays into nested hashes. Let's do it by | |
# calling this function recursively on each subtree. | |
for my $dev (keys %device_trees) { | |
if (@{ $device_trees{$dev} }) { | |
# Replace the flat array with a logically structured subtree. | |
$device_trees{$dev} = parse_devices( | |
lines => $device_trees{$dev}, | |
prefix => $prefix + 2, # the indent used by lsblk | |
); | |
} else { | |
# Even if the node is childless, we need to turn it from | |
# an empty array to an empty hash to make the structure | |
# consistent. | |
$device_trees{$dev} = {}; | |
} | |
} | |
return \%device_trees; | |
} | |
# Pretty print the device tree in a sorted manner. | |
sub print_devices { | |
my (%args) = @_; | |
my %devices = %{ $args{devices} }; | |
sub compare_sans_indent { | |
# Compare only the part follwing the tree drawn by lsblk, i.e. | |
# ignore every leading non-alpha character during the | |
# comparison. | |
my $re = qr/^[^a-zA-Z]*/; | |
$a =~ s/$re//r cmp $b =~ s/$re//r; | |
} | |
for (sort compare_sans_indent keys %devices) { | |
# The actual lines are stored in our keys. | |
print; | |
# Descend into the subtree and print it before continuing on | |
# this level. | |
print_devices(devices => $devices{$_}); | |
} | |
} | |
open(my $lsblk_fh, '-|', "/bin/lsblk", @ARGV); | |
my @lsblk = <$lsblk_fh>; | |
close $lsblk_fh; | |
my $devices = parse_devices(lines => \@lsblk); | |
print_devices(devices => $devices); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment