use v5.24;
use strict;
use warnings;
use File::Basename;
use Try::Tiny;
use List::Util 'uniq';
use Net::DBus;
my $bus = Net::DBus->system();
my $srv = $bus->get_service('org.freedesktop.UDisks2');
my $ud = $srv->get_object('/org/freedesktop/UDisks2/Manager');
sub filter_dev {
my ($device_path) = @_;
my $dev = $srv->get_object($device_path);
return unless $dev->_net_dbus_introspector->has_interface('org.freedesktop.UDisks2.Filesystem');
my $ignore = try { $dev->HintIgnore } catch { 1 };
return if $ignore;
my $mounted = try { $dev->MountPoints->@* } catch { 1 };
return if $mounted;
return $dev;
}
sub list {
return map { $_->IdLabel || $_->IdUUID }
map { filter_dev($_) }
@{$ud->GetBlockDevices({})};
}
sub mount {
my ($name) = @_;
my @devs = map { filter_dev($_) } uniq(
@{$ud->ResolveDevice({label=>$name},{})},
@{$ud->ResolveDevice({uuid=>$name},{})},
);
die "No device matching '$name'\n" unless @devs;
$_->Mount({}) for @devs;
}
my $cmd = basename($0);
if (!@ARGV) {
warn <<"EOF";
$cmd <name> # mount
$cmd --list # list names
$cmd --bashcomp # print completion code
EOF
exit 1;
}
elsif ($ARGV[0] eq '--list') {
say for list();
}
elsif ($ARGV[0] eq '--bashcomp') {
print <<"EOF";
_dmount_list() {
local -a list
local item
while read -r item; do
list+=( "$item")
done < <(dmount --list)
COMPREPLY=()
while read -r item; do
COMPREPLY+=( "${item@Q}" )
done < <( compgen -W "${list[*]@Q}" -- "$2" )
}
complete -F _dmount_list $cmd
EOF
}
else {
mount($ARGV[0]);
}