diff --git a/package-updates/package-updates-lib.pl b/package-updates/package-updates-lib.pl index df4609635..978916e2b 100644 --- a/package-updates/package-updates-lib.pl +++ b/package-updates/package-updates-lib.pl @@ -11,6 +11,7 @@ use Data::Dumper; $available_cache_file = "$module_config_directory/available.cache"; $current_cache_file = "$module_config_directory/current.cache"; +$updates_cache_file = "$module_config_directory/updates.cache"; $cron_cmd = "$module_config_directory/update.pl"; $yum_cache_file = "$module_config_directory/yumcache"; @@ -246,6 +247,37 @@ if (defined(&software::update_system_available)) { return ( ); } +sub supports_updates_available +{ +return defined(&software::update_system_updates); +} + +# updates_available(no-cache) +# Returns an array of hash refs of package updates available, according to +# the update system, with caching. +sub updates_available +{ +my ($nocache) = @_; +if (!defined(@updates_available_cache)) { + if ($nocache || &cache_expired($updates_cache_file)) { + # Get from original source + @updates_available_cache = &software::update_system_updates(); + foreach my $a (@updates_available_cache) { + $a->{'update'} = $a->{'name'}; + $a->{'system'} = $software::update_system; + } + &write_cache_file($updates_cache_file, + \@updates_available_cache); + } + else { + # Use on-disk cache + @updates_available_cache = + &read_cache_file($updates_cache_file); + } + } +return @updates_available_cache; +} + # package_install(package, [system]) # Install some package, either from an update system or from Webmin. Returns # a list of updated package names. @@ -314,28 +346,52 @@ sub list_possible_updates my ($nocache) = @_; my @rv; my @current = &list_current($nocache); -my @avail = &list_available($nocache == 1); -my %availmap; -foreach my $a (@avail) { - my $oa = $availmap{$a->{'name'},$a->{'system'}}; - if (!$oa || &compare_versions($a, $oa) > 0) { - $availmap{$a->{'name'},$a->{'system'}} = $a; +if (&supports_updates_available()) { + my %currentmap; + foreach my $c (@current) { + $currentmap{$c->{'name'},$c->{'system'}} ||= $c; } - } -foreach my $c (sort { $a->{'name'} cmp $b->{'name'} } @current) { - # Work out the status - my $a = $availmap{$c->{'name'},$c->{'system'}}; - if ($a->{'version'} && &compare_versions($a, $c) > 0) { - # A regular update is available + foreach my $a (&updates_available($nocache == 1)) { + my $c = $currentmap{$a->{'name'},$a->{'system'}}; + next if (!$c); + next if ($a->{'version'} eq $c->{'version'}); push(@rv, { 'name' => $a->{'name'}, 'update' => $a->{'update'}, 'system' => $a->{'system'}, 'version' => $a->{'version'}, 'oldversion' => $c->{'version'}, 'epoch' => $a->{'epoch'}, + 'oldepoch' => $c->{'epoch'}, 'security' => $a->{'security'}, - 'desc' => $c->{'desc'} || $a->{'desc'}, - 'severity' => 0 }); + 'desc' => $c->{'desc'} || $a->{'desc'} }); + } + } +else { + # Compute from current and available list + my @avail = &list_available($nocache == 1); + my %availmap; + foreach my $a (@avail) { + my $oa = $availmap{$a->{'name'},$a->{'system'}}; + if (!$oa || &compare_versions($a, $oa) > 0) { + $availmap{$a->{'name'},$a->{'system'}} = $a; + } + } + foreach my $c (sort { $a->{'name'} cmp $b->{'name'} } @current) { + # Work out the status + my $a = $availmap{$c->{'name'},$c->{'system'}}; + if ($a->{'version'} && &compare_versions($a, $c) > 0) { + # A regular update is available + push(@rv, { 'name' => $a->{'name'}, + 'update' => $a->{'update'}, + 'system' => $a->{'system'}, + 'version' => $a->{'version'}, + 'oldversion' => $c->{'version'}, + 'epoch' => $a->{'epoch'}, + 'oldepoch' => $c->{'epoch'}, + 'security' => $a->{'security'}, + 'desc' => $c->{'desc'} || $a->{'desc'}, + 'severity' => 0 }); + } } } return @rv; diff --git a/software/CHANGELOG b/software/CHANGELOG index dbd185c1b..270d1f958 100644 --- a/software/CHANGELOG +++ b/software/CHANGELOG @@ -30,3 +30,6 @@ The selected package and update systems are now checked when the module is opene ---- Changes since 1.470 ---- On Solaris, added support for the pkgutil command from Blastwave for installing packages, which replaces the old pkg-get. On Solaris, package versions are now shown in the package list and tree. +---- Changes since 1.500 ---- +Fixed several bugs related to YUM available package updates. +Added the update_system_updates function to more efficiently find available packages for YUM and APT. diff --git a/software/yum-lib.pl b/software/yum-lib.pl index dd15dbc69..f0bc12b24 100755 --- a/software/yum-lib.pl +++ b/software/yum-lib.pl @@ -196,21 +196,53 @@ while() { } } close(PKG); +&set_yum_security_field(\%done); +return @rv; +} -# Also run list-sec to find out which are security updates -&open_execute_command(PKG, "yum list-sec", 1, 1); +# set_yum_security_field(&package-hash) +# Set security field on packages which are security updates +sub set_yum_security_field +{ +local ($done) = @_; +&open_execute_command(PKG, "yum list-sec 2>/dev/null", 1, 1); while() { s/\r|\n//g; if (/^\S+\s+security\s+(\S+?)\-([0-9]\S+)\.([^\.]+)$/) { local ($name, $ver) = ($1, $2); - if ($done{$name}) { - $done{$name}->{'source'} = 'security'; - $done{$name}->{'security'} = 1; + if ($done->{$name}) { + $done->{$name}->{'source'} = 'security'; + $done->{$name}->{'security'} = 1; } } } close(PKG); +} +# update_system_updates() +# Returns a list of package updates available from yum +sub update_system_updates +{ +local @rv; +local %done; +&open_execute_command(PKG, "yum check-update 2>/dev/null", 1, 1); +while() { + s/\r|\n//g; + if (/^(\S+)\.([^\.]+)\s+(\S+)\s+(\S+)/) { + local $pkg = { 'name' => $1, + 'arch' => $2, + 'version' => $3, + 'source' => $4 }; + $pkg->{'version'} = $1; + if ($pkg->{'version'} =~ s/^(\S+)://) { + $pkg->{'epoch'} = $1; + } + $done{$pkg} = $pkg->{'name'}; + push(@rv, $pkg); + } + } +close(PKG); +&set_yum_security_field(\%done); return @rv; }