#!/usr/bin/perl

use strict;
use Carp;
my $file = $ARGV[0];

print "Kernel file: $file\nDetected version: ".kernel_version($file)."\n";
exit;

sub kernel_version {
    my $file = shift;
    my $version = '0.0.0';

    if(_is_gzip($file)) {
        open(IN,"gzip -dc $file |") or croak("Couldn't run gzip -dc $file");
    } else {
        open(IN,"<$file") or croak("Failed to open $file.");
    }

    while(<IN>) {
        # When Linux Kernel 4.0pre1 comes out, we'll have to change this
        if(/Linux\ version\ ([123]\.\d+\.[\w\-\.]+)/) {
            verbose("Found version '$1' at line # $.");
            $version = $1;
            last;
        }
    }
    #close(IN);

   if ($version eq "0.0.0") {
	# trying ia32 bzImage kind of thing
	my $buffer;
	if (seek(IN, 0x202, 0) && (read(IN, $buffer, 4) == 4) 
	    && (substr($buffer,0,4) eq "HdrS")
	    && seek(IN, 0x20e, 0) && (read(IN, $buffer, 2) == 2)) {
	    my $ofs = 0x200 + unpack("S", substr($buffer,0,2));
	    if (seek(IN, $ofs, 0) && (read(IN, $buffer, 80) == 80)) {
		$version = substr($buffer, 0, index($buffer, " "));
	    }
	}
   }
    close(IN);
    return $version;
}
sub debug {
    foreach my $line (@_) {
	print "$line\n";
    }
}
sub verbose {
    foreach my $line (@_) {
	print "$line\n";
    }
}
sub _is_gzip {
    my $file = shift;
    debug("opening $file to figure out if it is gzip archive");
    open(IN,"<$file") or (carp($!), return undef);
    my $chr1 = getc IN;
    my $chr2 = getc IN;
    debug(unpack("H*",$chr1));
    debug(unpack("H*",$chr2));
    close(IN) or (carp($!), return undef);
    if(unpack("H*",$chr2) eq "8b" and unpack("H*",$chr1) eq "1f") {
        debug("Is a gzip archive");
        return 1;
    } else {
        debug("Is not a gzip archive");
        return 0;
    }
}
