#!/usr/local/bin/perl -w # Fetch patches from Sun's public patch server. This is pretty much # duplicating a lot of the work done by other scripts, but heck, I # didn't know about them at the time. Sun's own tool is next to # useless if you don't have a Sunsolve login. # # Waider 1998ish use Net::FTP; use POSIX; # for uname $ftp = undef; # You may wish to edit these $PATCHHOST='sunsolve.sun.co.uk'; $PATCHDIR='/pub/patches'; $SHOWREV='/usr/bin/showrev -p'; # Check OS version $os = (uname)[0]; $osver = (uname)[2]; # Gah. SunOS $osver is 5.x instead of Solaris' 2.x. I guess subtract 3... $osver = $osver - 3 if ( $os eq 'SunOS' ); $RECOMMENDED=$osver.'_Recommended.README'; $|=1; print "Fetching $RECOMMENDED from Sun..."; maybe_fetch_file( $RECOMMENDED ); print "done.\n"; open( PLIST, "$SHOWREV|" ) || die $!; open( RECOM, "<$RECOMMENDED" ) || die $!; while( ) { (undef, $patch, undef) = split; ($id, $rev) = split(/-/, $patch); $erev = $installed{ $id }; $erev ||= '00'; $installed{ $id } = $rev if $rev > $erev; } %recommended = map { if ( /^[0-9][0-9][0-9][0-9][0-9][0-9]\-[0-9][0-9]\s+/ ) { chomp; ($patch, undef) = split; ($id, $rev) = split(/-/, $patch); $id => $rev ; } else { 'dud' => 'dud'; } } ; close( RECOM ); close( PLIST ); %patches = map { $_ => $_ } keys %installed; for( keys %recommended ) { $patches{ $_ } = $_ unless $_ =~ /dud/; } @patches = sort keys %patches; print "Patch Report\nID\tInstalled\tRecommended\tAction\n"; for( @patches ) { $inst = $installed{ $_ }; $rec = $recommended{ $_ }; $inst ||= '00'; $rec ||= '00'; $action = ( $inst < $rec ) ? "not installed..." : "installed\n"; printf "$_ \t%s\t\t%s\t\t%s", $inst, $rec, $action; if ( $action eq "not installed..." ) { while( !maybe_fetch_file( "$_-$rec.tar.Z" )) { print "."; } print "d/l'd.\n"; } } if ( $ftp ) { $ftp->close(); } sub maybe_fetch_file() { $file = shift; # check for local copy of the file if ( -r $file ) { # stat local copy, get mtime & size (undef, undef, undef, undef, undef, undef, undef, $locsz, undef, $loctm, undef, undef, undef ) = stat( $file ); } else { $locsz = 0; $loctm = 0; } # check if ftp connection is live, reopen if necessary if ( !defined( $ftp ) || !ref( $ftp ) || !$ftp->pwd ) { $ftp = Net::FTP->new( $PATCHHOST, Debug=>1 ); $ftp->login( 'anonymous', 'waider@scope.ie' ); $ftp->cwd( $PATCHDIR ); $ftp->pasv(); $ftp->binary(); } # FIXME check that file exists on server! # check mtime & size of remote copy $remsz = $ftp->size( $file ) or die $!; # if mtime of local is more recent & sizes match, return if ( $remsz == $locsz ) { $remtm = $ftp->mdtm( $file ); if ( $remtm <= $loctm ) { return 1; } } # fetch file # try to recover from partial fetch if ( $locsz ) { print "recovering..."; $ftp->get( $file, $file, $locsz ) or die $!; } else { print "fetching..."; $ftp->get( $file ) or die $!; } 1; }