File Coverage

blib/lib/Linux/KernelSort.pm
Criterion Covered Total %
statement 79 81 97.5
branch 26 28 92.8
condition 14 20 70.0
subroutine 7 7 100.0
pod 4 5 80.0
total 130 141 92.2


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Linux::KernelSort - Perl extension for sorting and comparing Linux
4             kernel versions. The expected kernel version naming convention is
5             the same naming convetion demonstrated by http://www.kernel.org.
6             NOTE: Currently, only the 2.6.x series of kernels (including -rc's,
7             -git's, and -mm's) are properly evaluated.
8              
9             =head1 SYNOPSIS
10              
11             use Linux::KernelSort;
12             my $kernel = new Linux::KernelSort;
13              
14             int $ret;
15             my $version1 = "2.6.19";
16             my $version2 = "2.6.19-rc2-git7";
17             $ret = $kernel->compare($version1, $version2);
18              
19             if ($ret == 0) {
20             print "$version1 and $version2 are the same version";
21             } elsif ($ret > 0) {
22             print "$version1 is newer than $version2";
23             } else {
24             print "$version1 is older than $version2";
25             }
26              
27             my @kernel_list = [ '2.6.15',
28             '2.6.18',
29             '2.6.18-rc2',
30             '2.6.18-rc2-git2',
31             '2.6.18-mm1',
32             '2.6.18-rc2-mm1' ];
33              
34             my @sorted_list = $kernel->sort($kernel_list);
35              
36             print "@sorted_list";
37              
38             =head1 DESCRIPTION
39              
40             Linux::KernelSort is intended to sort a list of kernel versions into
41             ascending order. It also provides the capability to compare
42             two kernel versions and determine if one version is newer, older,
43             or the same as the other version.
44              
45             =head1 FUNCTIONS
46              
47             =cut
48              
49             package Linux::KernelSort;
50              
51 1     1   25014 use strict;
  1         2  
  1         39  
52 1     1   6 use warnings;
  1         3  
  1         1067  
53              
54             our $VERSION = '0.01';
55              
56             sub new {
57 1     1 0 13 my $class = shift;
58 1         3 my $self = {};
59 1         4 $self->{debug} = 1;
60 1         4 bless ($self, $class);
61 1         3 return $self;
62             }
63              
64             =head2 version_check()
65             Purpose: Verify the version is valid and follows the
66             proper naming convention demonstrated by
67             http://www.kernel.org
68             Input: A string containing the kernel version
69             Return: 0 if version is valid
70             1 if version is invalid
71              
72             =cut
73              
74             sub version_check {
75 119     119 1 142 my $self = shift;
76 119   50     236 my $version = shift || return undef;
77              
78 119 100       622 if ( $version !~ m/^\d+\.\d+\.\d+(-rc\d+)?(-git\d+)?(-scsi-misc\d+)?(-scsi-rc-fixes\d+)?(-mm\d+)?$/ ) {
79 16 50       41 if ( $self->{debug} ) { print "Invalid Kernel Version: $version\n"; }
  0         0  
80 16         52 return 1;
81             }
82              
83 103         283 return 0;
84             }
85              
86             =head2 rank()
87              
88             Purpose: Generate a ranking for a given kernel version
89             Input: A string containing the kernel version which
90             follows the proper naming convention demonstrated
91             by http://www.kernel.org
92             Return: Kernel ranking
93              
94             =cut
95              
96             sub rank {
97 116     116 1 162 my $self = shift;
98 116   50     258 my $version = shift || return undef;
99              
100 116 100       182 if ( $self->version_check($version) ) {
101 15         31 return undef;
102             }
103              
104 101         299 $version =~ s/\.//g;
105 101         247 $version =~ m/^(\d+).*/;
106 101         181 my $rank = $1;
107              
108 101 100       274 if ( $version =~ m/-rc(\d+)/ ) {
109 48         66 my $rc = $1;
110 48         76 $rank = $rank - 1;
111 48         95 $rank = $rank . ".$rc";
112             } else {
113 53         81 $rank = $rank . ".0";
114             }
115              
116 101 100       198 if ( $version =~ m/-git(\d+)/ ) {
117 20         35 my $git = $1;
118 20         26 $rank = $rank . ".$git"
119             } else {
120 81         99 $rank = $rank . ".0";
121             }
122              
123 101 100       165 if ( $version =~ m/-scsi-misc(\d+)/ ) {
124 1         3 my $scsi_misc = $1;
125 1         3 $rank = $rank . ".$scsi_misc"
126             } else {
127 100         107 $rank = $rank . ".0";
128             }
129              
130 101 100       150 if ( $version =~ m/-scsi-rc-fixes(\d+)/ ) {
131 1         3 my $rc_fixes = $1;
132 1         3 $rank = $rank . ".$rc_fixes"
133             } else {
134 100         99 $rank = $rank . ".0";
135             }
136              
137 101 100       227 if ( $version =~ m/-mm(\d+)/ ) {
138 37         57 my $mm = $1;
139 37         57 $rank = $rank . ".$mm";
140             } else {
141 64         70 $rank = $rank . ".0"
142             }
143              
144 101         249 return $rank;
145             }
146              
147             =head2 compare()
148              
149             Purpose: Compare two kernel versions
150             Input: Strings ($kernel1, $kernel2) each containing a
151             kernel version which follows the proper naming
152             conventaion demonstrated by http://www.kernel.org
153             Return -1 if $kernel1 < $kernel2 (ie $kernel1 is older than $kernel2)
154             0 if $kernel1 == $kernel2 (ie $kernel1 is the same version as $kernel2)
155             1 if $kernel1 > $kernel2 (ie $kernel1 is newer than $kernel2)
156              
157             =cut
158              
159             sub compare {
160 54     54 1 70 my $self = shift;
161 54   50     130 my $kernel1 = shift || return undef;
162 54   50     106 my $kernel2 = shift || return undef;
163              
164 54         102 my $rank1 = $self->rank($kernel1);
165 54         111 my $rank2 = $self->rank($kernel2);
166              
167 54 100 66     192 if ( !$rank1 || !$rank2 ) {
168 11 50       25 if ( $self->{debug} ) { print "Unable to properly compare kernel versions: $kernel1, $kernel2\n"; }
  0         0  
169              
170 11 100 100     45 if ( !$rank1 && !$rank2 ) {
    100          
171 3         18 return 0;
172             } elsif ( !$rank1 ) {
173 4         27 return -1;
174             } else {
175 4         156 return 1;
176             }
177             }
178              
179 43   66     180 while (length($rank1) && length($rank2)) {
180 109         279 $rank1 =~ m/^(\d+)\.?(.*)/;
181 109         253 my $value1 = $1;
182 109         312 $rank1 = $2;
183              
184 109         261 $rank2 =~ m/^(\d+)\.?(.*)/;
185 109         180 my $value2 = $1;
186 109         152 $rank2 = $2;
187              
188 109 100       247 if ($value1 == $value2) {
    100          
189 67         304 next;
190             } elsif ($value1 < $value2) {
191 23         145 return -1;
192             } else {
193 19         89 return 1;
194             }
195             }
196              
197 1         7 return 0;
198             }
199              
200             =head2 sort()
201              
202             Purpose: Sort a list of kernel versions in ascending order.
203             Uses shell sort algorithm.
204             Input: Array of strings containing kernel versions which
205             follows the proper naming convention demonstrated
206             by http://www.kernel.org
207             Return: Sorted array
208              
209             =cut
210              
211             sub sort {
212 2     2 1 743 my $self = shift;
213 2         8 my (@kernels) = @_;
214              
215 2         3 my $size = @kernels;
216 2         12 for (my $gap = int($size/2); $gap > 0; $gap = int($gap/2)) {
217 5         13 for (my $i = $gap; $i < $size; $i++) {
218 37   100     151 for (my $j = $i-$gap; ($j >= 0) && ($self->compare($kernels[$j], $kernels[$j+$gap]) > 0); $j -= $gap) {
219 21         32 my $temp = $kernels[$j];
220 21         33 $kernels[$j] = $kernels[$j+$gap];
221 21         101 $kernels[$j+$gap] = $temp;
222             }
223             }
224             }
225              
226 2         20 return @kernels;
227             }
228              
229             =head1 AUTHOR
230              
231             Leann Ogasawara ogasawara@osdl.org
232              
233             =head1 COPYRIGHT AND LICENSE
234              
235             Linux-KernelSort is Copyright (c) 2006, by Leann Ogasawara.
236             All rights reserved. You may distribute this code under the terms
237             of either the GNU General Public License or the Artistic License,
238             as specified in the Perl README file.
239              
240             =cut
241              
242             1;
243              
244             __END__