Subject: Re: UP2DATE RedHat 6.1 Newsgroups: redhat.config Date: 2000/01/19 Or use this script instead of up2date. #!/usr/bin/perl # check-redhat-updates.pl # by Jonathan I. Kamens # Downloads the current file listing from ftp.redhat.com, compare the # RPMs listed in it to what's installed, print the RPMs that may be # updates. # # Command-line arguments: # # --rpm-list=fileSpecify a file containing a list of installed # RPMs, in the format output by "rpm -q -a". If # this isn't specified, the script runs "rpm -q # -a" to get the list. # --ls-file=file.gzSpecify the file containing a list of files # on the FTP site, in the format of # ftp://ftp.redhat.com/pub/ls-lR.gz. If this # isn't specified, the script retrieves that # file using ncftpget. # --save-lsIf specified, the script will save the # downloaded ls-lR.gz file when it's done and # tell you where the saved file is located. ### ### CONFIGURATION ### # I have this script configured for RedHat 6.1 on x86. You will # almost certainly want to change the configuration if you are using # another version of RedHat or another platform. The changes you need # to make should be obvious. If you're not sure, you can simply # remove all the configuration below indicating which files and # directories should be ignored, then run the script, then tweak the # configuration to get it to ignore the things in its output that you # can see are irrelevant to you. If you decide to do this, you'll # probably need to iterate several times; use --save-ls the first time # to save the ls-lR.gz from the FTP site so you don't have to keep # downloading it over and over again. # The FTP server to get the file listing from $ftp_host = 'ftp.redhat.com'; # The file to retrieve $ftp_file = '/pub/ls-lR.gz'; # If this array is non-empty, then any FTP directory whose name # matches one of the regular expressions in it will be ignored. @dir_ignore_regexps = ( # We're using libc6 so, ignore libc5 packages '\blibc5\b', # Ignore all non-x86 platforms '\b(alpha|ppc|mipseb|sparc|m68k)\b', # Ignore redhat releases prior to 6.1 '\b(updates/|redhat-)([245]\.|6\.0)\b', ); # If this array is non-empty, then any RPMs whose file name matches # one of the regular expressions in it will be ignored. @file_ignore_regexps = ( # I don't want any pre-built kernel packages # since I build my own kernel and modules. '^kernel-(pcmcia|smp|\d)', ); ### ### END CONFIGURATION ### You probably don't need to change anything below here. ### use Getopt::Long; ($ftp_basename = $ftp_file) =~ s,.*/,,; ($whoami = $0) =~ s,.*/,,; $td = "/tmp/$whoami.$$"; $usage = "Usage: $whoami [ --rpm-list=file ] [ --ls-file=file.gz ] [ --save-ls ]\n"; die $usage if (! GetOptions('rpm-list=s' => \$rpm_list, 'ls-file=s' => \$ls_file, 'save-ls' => \$save_ls)); die "$whoami: Can't specify both --ls-file and --save-ls options\n$usage" if ($ls_file && $save_ls); if (! ($ls_file || -d $td)) { mkdir($td, 0755) || die; } if ($rpm_list) { open(RPM, $rpm_list) || die "$whoami: opening $rpm_list: $!\n$usage"; } else { open(RPM, 'rpm -q -a|') || die "$whoami: opening 'rpm -q -a': $!\n"; } while () { chop; ($package, $version, $release) = &split_rpm_file($_); $versions{$package} = $version; $releases{$package} = $release; } close(RPM); if (! $ls_file) { if (system('ncftpget', '-F', '-r', 10, '-t', 60, $ftp_host, $td, $ftp_file)) { rmdir($td); die; } $open_file = "$td/$ftp_basename"; } else { $open_file = $ls_file; } if ($open_file =~ /\.gz$/) { $open_file = "zcat $open_file|"; } open(LS, $open_file) || die; line: while () { chop; if (/^(\S+):$/) { $dir = $1; foreach $regexp (@dir_ignore_regexps) { if ($dir =~ /$regexp/) { $dir = undef; } } next; } next if (! $dir); # Ignore source RPMS -- we're only interested in installable packages if (/\.src\.rpm$/) { next; } if (/ (\S+)(\.[^.]+\.rpm(.rhmask)?)$/) { $base_name = $1; $file = $base_name . $2; foreach $regexp (@file_ignore_regexps) { if ($file =~ /$regexp/) { next line; } } $file = "$dir/$file"; ($package, $version, $release) = &split_rpm_file($base_name); if (&is_contrib_dir($dir)) { $contrib_versions{$package} = $version; $contrib_releases{$package} = $release; $contrib_files{$package} = $file; next; } delete $contrib_versions{$package}; delete $contrib_releases{$package}; delete $contrib_files{$package}; &compare_rpms($package, $version, $release, $file); } } close(LS); foreach $package (keys %contrib_versions) { &compare_rpms($package, $contrib_versions{$package}, $contrib_releases{$package}, $contrib_files{$package}); } if (! $ls_file) { if ($save_ls) { print "File listing saved in $td/ls-lR.gz\n"; } else { unlink("$td/ls-lR.gz"); rmdir($td); } } sub split_rpm_file { local($_) = @_; /^(.*)-([^-]+)-([^-]+)$/; } sub is_contrib_dir { local($_) = @_; m,(^|/)contrib(/|$), } sub compare_rpms { my($package, $version, $release, $file) = @_; return if ($printed{"$package-$version-$release"}); # If the installed package is a "us" version on the package on the # FTP site isn't, ignore it. return if ($releases{$package} =~ /(\d|\b)us\b/ && $release !~ /us/); if (defined($versions{$package})) { my($cmp_versions) = &compare_versions($versions{$package}, $version); if (($cmp_versions < 0) || (($cmp_versions == 0) && ($releases{$package} < $release))) { print("$file may be new ", "($package-$versions{$package}-$releases{$package} installed)\n"); $printed{"$package-$version-$release"}++; } } } sub compare_versions { my($version1, $version2) = @_; my(@version1, @version2); my($key1, $key2); @version1 = split(/\./, $version1); @version2 = split(/\./, $version2); while (defined($key1 = shift @version1)) { $key2 = shift @version2; return 1 if (! $key2); return -1 if ($key1 < $key2); return 1 if ($key1 > $key2); return -1 if ($key1 lt $key2); return 1 if ($key1 gt $key2); } return -1 if (@version2); return 0; }