package Linux::Info::KernelRelease; use strict; use warnings; use Carp qw(confess carp); use Set::Tiny 0.04; use Linux::Info::KernelSource; use Class::XSAccessor getters => { get_raw => 'raw', get_major => 'major', get_minor => 'minor', get_patch => 'patch', get_compiled_by => 'compiled_by', get_gcc_version => 'gcc_version', get_type => 'type', get_build_datetime => 'build_datetime', }; our $VERSION = '2.13'; # VERSION # ABSTRACT: parses and provide Linux kernel detailed information sub _set_proc_ver_regex { my $self = shift; $self->{proc_regex} = undef; } sub _parse_proc_ver { my $self = shift; my $line; if ( defined $self->{raw} ) { $line = $self->{raw}; } elsif ( defined $self->{source} ) { $line = $self->{source}->get_version; $self->{raw} = $line; } else { confess 'Inconsistent object state: no raw string or source to use'; } if ( $line =~ $self->{proc_regex} ) { my @required = qw(compiled_by gcc_version build_datetime version); foreach my $key (@required) { confess "Missing '$key' in the regex match groups" unless ( exists $+{$key} ); } map { $self->{$_} = $+{$_} } ( keys %+ ); } else { confess( "Failed to match '$line' against '" . $self->{proc_regex} . '\'' ); } } # regex must be relaxed because distros can put anything after the first three # digits my $version_regex = qr/^(\d+)\.(\d+)\.(\d+)/; sub _parse_version { my ( $self, $raw ) = @_; $raw =~ $version_regex; $self->{major} = $1 + 0; $self->{minor} = $2 + 0; $self->{patch} = $3 + 0; } sub new { my ( $class, $release, $source ) = @_; my $self = {}; bless $self, $class; if ( defined($release) ) { confess "The string for release '$release' is invalid" unless ( $release =~ $version_regex ); $self->{raw} = $release; $self->_parse_version($release); $self->{source} = undef; } else { my $source_class = 'Linux::Info::KernelSource'; if ( defined($source) ) { confess "Must receive a instance of $source_class" unless ( ( ref $source ne '' ) and ( $source->isa($source_class) ) ); } else { $source = $source_class->new; } $self->{source} = $source; $self->_set_proc_ver_regex; if ( defined( $self->{proc_regex} ) ) { $self->_parse_proc_ver; } $self->_parse_version( $self->{source}->get_sys_osrelease ); } return $self; } sub _validate_other { my ( $self, $other ) = @_; my $class = ref $self; my $other_ref = ref $other; confess 'The other parameter must be a reference' if ( $other_ref eq '' ); confess 'The other instance must be a instance of' . $class . ', not ' . $other_ref unless ( $other->isa($class) ); } sub _ge_version { my ( $self, $other ) = @_; $self->_validate_other($other); return 1 if ( $self->{major} > $other->get_major ); return 0 if ( $self->{major} < $other->get_major ); return 1 if ( $self->{minor} > $other->get_minor ); return 0 if ( $self->{minor} < $other->get_minor ); return 1 if ( $self->{patch} > $other->get_patch ); return 0 if ( $self->{patch} < $other->get_patch ); return 1; } sub _gt_version { my ( $self, $other ) = @_; $self->_validate_other($other); return 1 if ( $self->{major} > $other->get_major ); return 0 if ( $self->{major} < $other->get_major ); return 1 if ( $self->{minor} > $other->get_minor ); return 0 if ( $self->{minor} < $other->get_minor ); return 1 if ( $self->{patch} > $other->get_patch ); return 0 if ( $self->{patch} < $other->get_patch ); return 0; } sub _lt_version { my ( $self, $other ) = @_; $self->_validate_other($other); return 0 if ( $self->{major} > $other->get_major ); return 1 if ( $self->{major} < $other->get_major ); return 0 if ( $self->{minor} > $other->get_minor ); return 1 if ( $self->{minor} < $other->get_minor ); return 0 if ( $self->{patch} > $other->get_patch ); return 1 if ( $self->{patch} < $other->get_patch ); return 0; } use overload '>=' => '_ge_version', '>' => '_gt_version', '<' => '_lt_version'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Linux::Info::KernelRelease - parses and provide Linux kernel detailed information =head1 VERSION version 2.13 =head1 SYNOPSIS Getting the current kernel information: my $sys = Linux::Info::SysInfo->new; my $current = Linux::Info::KernelRelease->new; Or using L syntax sugar to achieve the same result: my $sys = Linux::Info::SysInfo->new; my $current = $sys->get_detailed_kernel; Or using a given Linux kernel release string: my $kernel = Linux::Info::KernelRelease->new('2.4.20-0-generic'); Now you can compare both: if ($current > $kernel) { say 'Kernel was upgraded!'; } =head1 DESCRIPTION This module parses the Linux kernel information obtained from sources like the C command and others. This make it easier to fetch each information piece of information from the string and also to compare different kernel versions, since instances of this class overload operators like ">=", ">" and "<". =head1 METHODS =head2 new Creates a new instance. Optionally, it might receive the following arguments: =over =item 1. A string as parameter like the kernel release information from F. =item 2. A instance of L. =back The string, if defined, will always have preference to setup the version based on it and the instance passed will be ignored. If you want to use L, be sure to pass C as the first argument. If none arguments are passed, a new instance of L will be created, and the default locations of files to parsed will be used. This method will also invoke the C<_set_proc_ver_regex> method, used to parse the string at F. Subclasses must override this method, since this class won't know how to do it. =head2 get_raw Returns the raw information stored, as read from F or passed to the C method. =head2 get_major Returns from the version, returns the integer corresponding to the major number. =head2 get_minor Returns from the version, returns the integer corresponding to the minor number. =head2 get_patch From the version, returns the integer corresponding to the patch number. =head2 get_build_datetime Returns a string representing when the kernel was built, or C if not possible to parse it. =head2 get_compiled_by Returns a string, representing the user who compiled the kernel, or C if not possible to parse it. =head2 get_gcc_version Returns a string, representing gcc compiler version used to compile the kernel, or C if not possible to parse it. =head2 get_type Returns a string, representing the features which define the kernel type, or C if not possible to parse it. =head1 SEE ALSO =over =item * https://www.unixtutorial.org/use-proc-version-to-identify-your-linux-release/ =back =head1 AUTHOR Alceu Rodrigues de Freitas Junior =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2015 by Alceu Rodrigues de Freitas Junior. This is free software, licensed under: The GNU General Public License, Version 3, June 2007 =cut