#! /usr/bin/perl

# copyright Thomas Lange 2001-2010, lange@debian.org
# copyright Michael Goetze 2011, mgoetze@mgoetze.net
# map "normal" device notation to grub notation

# TODO: read from stdin if no parameter given

use strict;

use Cwd 'abs_path';

my $grubdevice;
my %map;

my $device=shift;
my $devicemap = `mktemp`;
chomp $devicemap;
my $devbyid = "/dev/disk/by-id";

system("/usr/sbin/grub-mkdevicemap", "-m", "$devicemap") == 0 or die "Could not run grub-mkdevicemap\n";

open (DEVICEMAP,"<$devicemap") || die "Can't open device map $devicemap\n";
while (<DEVICEMAP>) {
  my ($grubdevice,$olddevice) = split;
  $map{$olddevice} = $grubdevice;
}

$device=~ m#^(/dev/(?:[shv]d\D|xvd\D|i2o/hd\D|ida/c\d*d\d*|cciss/c\d*d\d*|nvme\d+n1|mmcblk\d+))p?(\d*)$# || die "Can't match device: $device\n";
my ($disk,$partition) = ($1,$2);

if ($map{$disk}) {
  $grubdevice=$map{$disk};
} else {
  opendir (my $dh, $devbyid) || die "Can't open /dev/disk/by-id\n";

  while (my $diskid = readdir $dh) {
    next if ($diskid =~ /^[.].*/);

    $diskid = "$devbyid/$diskid";
    my $shortdev = abs_path($diskid);

    if (($shortdev eq $disk) && $map{$diskid}) {
      $grubdevice = $map{$diskid};
      last;
    }
  }

  closedir $dh;
  die "No match in $devicemap for $disk\n" unless $grubdevice;
}

if ($partition) {
  $partition--;
  $grubdevice=~s/\)/,$partition\)/;
}

print "$grubdevice\n";
unlink("$devicemap");
exit 0;
