Advertisement
derobert

Caching wrapper for grub-probe

Jun 14th, 2019
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.99 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use 5.028;
  3. use strict;
  4. use warnings qw(all);
  5. use autodie qw(mkdir);
  6.  
  7. use Data::Dump qw(pp);
  8. use Digest::SHA qw(sha256_hex);
  9. use File::Copy qw(copy);
  10. use File::Slurper qw(write_text read_text);
  11. use IPC::Run3;
  12.  
  13. my %cached = (
  14.     abstraction        => 1,
  15.     compatibility_hint => 1,
  16.     device             => 0,    # no need, fast
  17.     fs                 => 1,
  18.     fs_uuid            => 1,
  19.     hints_string       => 1,
  20.     partmap            => 1,
  21. );
  22.  
  23. my $cachedir = '/var/cache/local-grub-probe';
  24. my $real = 'grub-probe.cache-real';
  25.  
  26. unless (-d $cachedir) {
  27.     mkdir($cachedir);
  28. }
  29.  
  30. my @targets = find_targets();
  31. if (0 == @targets) {
  32.     warn "No --target argument?";
  33.     forward_to_real(); # does not return
  34. } elsif (1 == @targets) {
  35.     my $target = $targets[0];
  36.     exists $cached{$target}
  37.         or warn "Unknown target $target (treating as uncached)";
  38.     if ($cached{$target}) {
  39.         exit handle_cached();
  40.     } else {
  41.         forward_to_real() # does not return;
  42.     }
  43. } else {
  44.     warn "Multiple --target arguments";
  45.     forward_to_real(); # does not return;
  46. }
  47.  
  48. sub find_targets {
  49.     my @targets;
  50.     for (my $i = 0; $i < @ARGV; ) {
  51.         if ($ARGV[$i] eq '-t') {
  52.             push @targets, $ARGV[1+$i];
  53.             $i += 2;
  54.         } elsif ($ARGV[$i] =~ /^--target=(.+)$/) {
  55.             push @targets, $1;
  56.             $i += 1;
  57.         } else {
  58.             $i += 1
  59.         }
  60.     }
  61.  
  62.     return @targets;
  63. }
  64.  
  65. sub forward_to_real { exec {$real} 'grub-probe', @ARGV }
  66.  
  67. sub handle_cached {
  68.     my $hash = sha256_hex(join(q{!}, @ARGV));
  69.     my $cmd = "$cachedir/$hash.cmd"; # final one written + useful debug
  70.     my $out = "$cachedir/$hash.out";
  71.     my $err = "$cachedir/$hash.err";
  72.     my $res = "$cachedir/$hash.res";
  73.  
  74.     -e $cmd || run_and_cache($cmd, $res, $out, $err);
  75.  
  76.     copy($out, \*STDOUT);
  77.     copy($err, \*STDERR);
  78.  
  79.     return 0+read_text($res);
  80. }
  81.  
  82. sub run_and_cache {
  83.     my ($cmd, $res, $out, $err) = @_;
  84.  
  85.     run3 [ $real, @ARGV ], undef, $out, $err;
  86.     ($? & 0xFF) and die "$real died terribly: $?";
  87.     write_text($res, ($?>>8)."\n");
  88.     write_text($cmd, scalar(pp @ARGV)."\n");
  89.     return;
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement