Index: trunk/tools/ts-specs/base-specs/curl.spec |
— | — | @@ -5,7 +5,7 @@ |
6 | 6 | # |
7 | 7 | Name: TScurl |
8 | 8 | Summary: curl - Get a file from FTP or HTTP server. |
9 | | -Version: 7.18.2 |
| 9 | +Version: 7.19.0 |
10 | 10 | URL: http://curl.haxx.se/ |
11 | 11 | Source: http://curl.haxx.se/download/curl-%{version}.tar.bz2 |
12 | 12 | SUNW_BaseDir: %{_basedir} |
Index: trunk/tools/ts-specs/TSpca.spec |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +%include Solaris.inc |
| 3 | + |
| 4 | +Name: TSpca |
| 5 | +Summary: Patch Check Advanced |
| 6 | +Version: 20080911-01 |
| 7 | +Source1: pca |
| 8 | + |
| 9 | +SUNW_BaseDir: %{_basedir} |
| 10 | +BuildRoot: %{_tmppath}/%{name}-%{version}-build |
| 11 | +%include default-depend.inc |
| 12 | + |
| 13 | +# Requires: |
| 14 | + |
| 15 | +%prep |
| 16 | +%setup -q -T -c -n %name-%version |
| 17 | +cp %SOURCE1 . |
| 18 | + |
| 19 | +%build |
| 20 | + |
| 21 | +%install |
| 22 | +rm -rf $RPM_BUILD_ROOT |
| 23 | +mkdir -p $RPM_BUILD_ROOT%{_bindir} |
| 24 | +cp pca $RPM_BUILD_ROOT%{_bindir} |
| 25 | + |
| 26 | +%clean |
| 27 | +rm -rf $RPM_BUILD_ROOT |
| 28 | + |
| 29 | +%files |
| 30 | +%defattr (-, root, bin) |
| 31 | +%dir %attr (0755, root, bin) %{_bindir} |
| 32 | +%attr (0755, root, bin) %{_bindir}/pca |
| 33 | + |
| 34 | +%changelog |
| 35 | +* Thu Oct 9 2008 - river@wikimedia.org |
| 36 | +- initial spec |
Index: trunk/tools/ts-specs/TSnicstat.spec |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +%include Solaris.inc |
| 3 | + |
| 4 | +Name: TSnicstat |
| 5 | +Summary: iostat(1m)-like utility for network interfaces |
| 6 | +Version: 1 |
| 7 | +Source1: http://blogs.sun.com/roller/resources/timc/nicstat.c |
| 8 | + |
| 9 | +SUNW_BaseDir: %{_basedir} |
| 10 | +BuildRoot: %{_tmppath}/%{name}-%{version}-build |
| 11 | +%include default-depend.inc |
| 12 | + |
| 13 | +# Requires: |
| 14 | + |
| 15 | +%prep |
| 16 | +%setup -q -T -c -n %name-%version |
| 17 | +cp %SOURCE1 . |
| 18 | + |
| 19 | +%build |
| 20 | + |
| 21 | +cc nicstat.c -o nicstat -lkstat -lrt -lsocket -lgen |
| 22 | + |
| 23 | +%install |
| 24 | +rm -rf $RPM_BUILD_ROOT |
| 25 | +mkdir -p $RPM_BUILD_ROOT%{_bindir} |
| 26 | +cp nicstat $RPM_BUILD_ROOT%{_bindir} |
| 27 | + |
| 28 | +%clean |
| 29 | +rm -rf $RPM_BUILD_ROOT |
| 30 | + |
| 31 | +%files |
| 32 | +%defattr (-, root, bin) |
| 33 | +%dir %attr (0755, root, bin) %{_bindir} |
| 34 | +%{_bindir}/nicstat |
| 35 | + |
| 36 | +%changelog |
| 37 | +* Thu Oct 9 2008 - river@wikimedia.org |
| 38 | +- initial spec |
Index: trunk/tools/ts-specs/ext-sources/pca |
— | — | @@ -0,0 +1,3757 @@ |
| 2 | +#!/bin/sh |
| 3 | +#! -*- perl -*- |
| 4 | +eval 'exec perl -x -w $0 ${1+"$@"}' |
| 5 | + if 0; |
| 6 | + |
| 7 | +# PCA - Patch Check Advanced |
| 8 | +# Analyze, download and install patches for Sun Solaris |
| 9 | +# |
| 10 | +# Author : Martin Paul <martin@par.univie.ac.at> |
| 11 | +# Home : http://www.par.univie.ac.at/solaris/pca/ |
| 12 | +my $version='20080911-01'; |
| 13 | + |
| 14 | +use strict; |
| 15 | +use Config; |
| 16 | + |
| 17 | +# Default paths |
| 18 | +my $unzip= '/usr/bin/unzip'; |
| 19 | +my $showrev= '/usr/bin/showrev'; |
| 20 | +my $pkginfo= '/usr/bin/pkginfo'; |
| 21 | +my $pkgchk= '/usr/sbin/pkgchk'; |
| 22 | +my $uncompress= '/usr/bin/uncompress'; |
| 23 | +my $tar= '/usr/sbin/tar'; |
| 24 | +my $uname= '/usr/bin/uname'; |
| 25 | +my $pager= '/usr/bin/more'; |
| 26 | + |
| 27 | +# Supported options, format is: |
| 28 | +# Long name, short name, argument type, argument text, default value, help |
| 29 | +my @options=( |
| 30 | + "list|l|||0|List patches", |
| 31 | + "listhtml|L|||0|List patches, produce HTML output", |
| 32 | + "download|d|||0|Download patches", |
| 33 | + "install|i|||0|Install patches", |
| 34 | + "pretend|I|||0|Pretend to install patches", |
| 35 | + "readme|r|||0|Display patch READMEs", |
| 36 | + "getxref|x|||0|Download patch xref file", |
| 37 | + "xrefdir|X|s|DIR|/var/tmp|Location of patch xref file", |
| 38 | + "nocheckxref|y|||0|Do not check for updated patch xref file", |
| 39 | + "xrefown||||0|Give write permissions on xref file to user only", |
| 40 | + "nocache||||0|Tell proxy to not cache xref file", |
| 41 | + "patchdir|P|s|DIR|.|Patch download directory", |
| 42 | + "askauth|a|||0|Ask for Sun Online Account data interactively", |
| 43 | + "user||s|USER||Sun Online Account user name", |
| 44 | + "passwd||s|PASS||Sun Online Account password", |
| 45 | + "localurl||s|URL||DEPRECATED", |
| 46 | + "patchurl||s|URL||Local URL for patches and READMEs", |
| 47 | + "xrefurl||s|URL||Local URL for patchdiag.xref", |
| 48 | + "stop||s@|ID||Stop after patch ID", |
| 49 | + "ignore||s@|ID||Ignore patch ID", |
| 50 | + "rec||s@|ID||Set Recommended flag on patch ID", |
| 51 | + "sec||s@|ID||Set Security flag on patch ID", |
| 52 | + "pattern|p|s|REGEX||List only patches whose synopsis matches REGEX", |
| 53 | + "noreboot|n|||0|Install only patches which do not require a reboot", |
| 54 | + "minage||i|DAYS|0|List only patches which are at least DAYS old", |
| 55 | + "maxage||i|DAYS|0|List only patches which are at most DAYS old", |
| 56 | + "syslog||s|TYPE||Log successful patch installs to syslog facility TYPE", |
| 57 | + "nobackup|k|s@|ID||Do not back up files to be patched for patch ID", |
| 58 | + "backdir|B|s|DIR||Saves patch backout data to DIR", |
| 59 | + "safe|s|||0|Check locally modified files for safe patch installation", |
| 60 | + "currentzone|G|||0|Make patchadd install patches in the current zone only", |
| 61 | + "patchadd||s|FILE|/usr/sbin/patchadd|Path to patchadd command", |
| 62 | + "noheader|H|||0|Don't display descriptive headers", |
| 63 | + "format||s|FORMAT|%p %i %e %c %r%s%b %a %y|Set output format to FORMAT", |
| 64 | + "fromfiles|f|s|DIR||Read uname/showrev/pkginfo output from files in DIR", |
| 65 | + "dltries||i|NUM|1|Try downloads from Sun download server NUM times", |
| 66 | + "force|F|||0|Force local caching proxy to download from Sun server", |
| 67 | + "root|R|s|DIR||Alternative root directory", |
| 68 | + "wget||s|FILE|/usr/sfw/bin/wget /usr/local/bin/wget /opt/csw/bin/wget /usr/bin/wget|Path to wget command", |
| 69 | + "wgetproxy||s|URL||Default proxy for wget", |
| 70 | + "logger||s|FILE|/usr/bin/logger|Path to logger command", |
| 71 | + "threads|t|i|NUM|0|Use NUM download threads" . ($Config{useithreads} ? '' : ' (DISABLED, Perl lacks ithreads)'), |
| 72 | + "update||s|TYPE|never|Update pca (TYPE is never, check, now or auto)", |
| 73 | + "pcaurl||s|URL|http://www.par.univie.ac.at/solaris/pca/stable/|URL for pca update", |
| 74 | + "ssprot||s|PROT|http|Protocol used to access sunsolve (http or https)", |
| 75 | + "sshost||s|HOST|sunsolve.sun.com|HOST name or IP address for sunsolve", |
| 76 | + "cffile||s@|FILE||Read FILE as additional configuration file", |
| 77 | + "debug|V|||0|Print debug information", |
| 78 | + "help|h|||0|Display this help", |
| 79 | + "man|m|||0|Display manual page", |
| 80 | + "version|v|||0|Display version information", |
| 81 | + "operands||||missing|ENVFILE", |
| 82 | + "tmpdir||||/tmp|INTERNAL", |
| 83 | + "proxy||||0|INTERNAL", |
| 84 | + "pforce||||0|INTERNAL", |
| 85 | + "dbgfile||||/tmp/pca-proxy-debug.txt|INTERNAL" |
| 86 | +); |
| 87 | + |
| 88 | +# Modules |
| 89 | +use Getopt::Long; |
| 90 | +use Time::Local; |
| 91 | +use Cwd; |
| 92 | +use File::Path; |
| 93 | +use Fcntl; |
| 94 | +use File::Basename; |
| 95 | +use File::Copy; |
| 96 | + |
| 97 | +# Variable declarations |
| 98 | +my (%o, %input, %p, %pkgs, %u, %c, %locks, %rloop); |
| 99 | +my (@plist, @slist, @rlist); |
| 100 | +my $conf_dbg=''; my %conf_read; |
| 101 | +my $dlfile=''; |
| 102 | +my $sttyset=0; |
| 103 | +my $patchxdir=''; |
| 104 | +my $currenttime=time(); |
| 105 | +my $queue; |
| 106 | +my %a; |
| 107 | +my $download_start; |
| 108 | +my $stopreached=0; |
| 109 | +my $wgetv=''; |
| 110 | + |
| 111 | +# Force flush to stdout right after every print command without "\n" |
| 112 | +$|= 1; |
| 113 | + |
| 114 | +# Set signal handler |
| 115 | +$SIG{HUP} = 'IGNORE'; |
| 116 | +$SIG{TERM} = $SIG{INT} = $SIG{QUIT} = \&handler; |
| 117 | + |
| 118 | +# Main |
| 119 | +# |
| 120 | +parse_args(); |
| 121 | +check_prerequisites(); |
| 122 | +import_threads(); |
| 123 | +process_patch_exceptions(); |
| 124 | +process_patch_flags(); |
| 125 | +update(); |
| 126 | + |
| 127 | +$o{proxy} && proxy(); |
| 128 | + |
| 129 | +expand_operands(); |
| 130 | + |
| 131 | +if ($o{readme} && ("@slist" =~ /^(\d{6}-\d{2} *)+$/)) { |
| 132 | + foreach my $pp (@slist) { |
| 133 | + my ($id, $rev)= split (/-/, $pp); |
| 134 | + init_patch ($id); |
| 135 | + $p{$id}{prev}=$rev; |
| 136 | + push (@plist, $id); |
| 137 | + } |
| 138 | + do_patch_list(); |
| 139 | + exit 0; |
| 140 | +} |
| 141 | + |
| 142 | +get_current_xref(); |
| 143 | +if (!$o{list} && !$o{download} && !$o{install} && !$o{readme}) { exit 0 } |
| 144 | + |
| 145 | +get_uname(); |
| 146 | +get_installed_packages(); |
| 147 | +get_installed_patches(); |
| 148 | +get_current_patches(); |
| 149 | +create_patch_list(); |
| 150 | +print_header(); |
| 151 | +do_patch_list(); |
| 152 | +print_footer(); |
| 153 | + |
| 154 | +exit 0; |
| 155 | + |
| 156 | +# Functions |
| 157 | + |
| 158 | +sub download_patch_worker { |
| 159 | + my $pp; |
| 160 | + { # signal the download loop that we're ready... |
| 161 | + lock $download_start; |
| 162 | + if (!defined($download_start)) { # if we haven't already |
| 163 | + $download_start = 0; |
| 164 | + dbg ("Broadcasting download worker ready"); |
| 165 | + cond_broadcast(\$download_start); |
| 166 | + } |
| 167 | + } |
| 168 | + { # wait for the download loop to tell us to start |
| 169 | + lock $download_start; |
| 170 | + dbg ("Waiting for download loop broadcast"); |
| 171 | + cond_wait(\$download_start) until $download_start == 1; |
| 172 | + } |
| 173 | + while (defined($pp = $queue->dequeue())) { |
| 174 | + my ($id, $rev) = split /-/, $pp; |
| 175 | + BEGIN { $^W = 0 } |
| 176 | + $p{$id}{worker_tid} = threads->self->tid(); |
| 177 | + BEGIN { $^W = 1 } |
| 178 | + $p{$id}{worker_done} = 0; |
| 179 | + dbg ("Worker " . $p{$id}{worker_tid} . " downloading " . $pp); |
| 180 | + download_patch($pp); |
| 181 | + $p{$id}{worker_done} = 1; |
| 182 | + } |
| 183 | + $queue->enqueue(undef); |
| 184 | +} |
| 185 | + |
| 186 | +sub buffer_worker_out { |
| 187 | + my $id = shift; |
| 188 | + my $cat = shift; |
| 189 | + |
| 190 | + if (!$o{threads}) { |
| 191 | + return (out ($cat, @_)); |
| 192 | + } |
| 193 | + |
| 194 | + my $ar = &share([]); |
| 195 | + @{$ar} = ($cat, @_); |
| 196 | + lock $p{$id}; |
| 197 | + push @{$p{$id}{output}}, $ar; |
| 198 | +} |
| 199 | + |
| 200 | +sub unbuffer_worker_out { |
| 201 | + my $id = $_[0]; |
| 202 | + lock $p{$id}; |
| 203 | + while (my $ar = shift @{$p{$id}{output}}) { |
| 204 | + if (@{$ar}) { |
| 205 | + my $cat = shift @{$ar}; |
| 206 | + out ($cat, @{$ar}); |
| 207 | + } |
| 208 | + } |
| 209 | +} |
| 210 | + |
| 211 | +sub do_patch_list { |
| 212 | + (@plist) || return; |
| 213 | + |
| 214 | + my @workers; |
| 215 | + for (my $i = 0; $i < $o{threads}; $i ++) { |
| 216 | + dbg ("Creating worker"); |
| 217 | + BEGIN { $^W = 0 } |
| 218 | + push @workers, threads->new(\&download_patch_worker); |
| 219 | + BEGIN { $^W = 1 } |
| 220 | + } |
| 221 | + |
| 222 | + # Counters |
| 223 | + $c{current}=0; |
| 224 | + $c{total}=$#plist+1; |
| 225 | + $c{dl}=$c{skipdl}=$c{faildl}=$c{inst}=$c{skipinst}=$c{failinst}=0; |
| 226 | + $c{p_ci}=$c{p_bi}=$c{p_c}=$c{p_b}=0; |
| 227 | + |
| 228 | + foreach my $id (@plist) { |
| 229 | + $c{current}++; |
| 230 | + |
| 231 | + # Add revision to patch id |
| 232 | + my $pp=""; |
| 233 | + ($p{$id}{irev} ne "00") && ($pp="$id-$p{$id}{irev}"); |
| 234 | + ($p{$id}{crev} ne "00") && ($pp="$id-$p{$id}{crev}"); |
| 235 | + ($p{$id}{prev} ne "00") && ($pp="$id-$p{$id}{prev}"); |
| 236 | + $pp || err ("Unknown patch-id $id"); |
| 237 | + # Remember revised patch id for later use |
| 238 | + $p{$id}{pp} = $pp; |
| 239 | + if ($o{threads}) { |
| 240 | + $queue->enqueue($pp); |
| 241 | + } |
| 242 | + } |
| 243 | + |
| 244 | + if ($o{threads}) { |
| 245 | + $queue->enqueue(undef); |
| 246 | + } |
| 247 | + |
| 248 | + $c{current}=0; |
| 249 | + |
| 250 | + foreach my $id (@plist) { |
| 251 | + $c{current}++; |
| 252 | + |
| 253 | + my $pp = $p{$id}{pp}; |
| 254 | + |
| 255 | + if ($o{list} || $o{download} || $o{install}) { |
| 256 | + print_patch ($id); |
| 257 | + } |
| 258 | + if ($o{download} || $o{install}) { |
| 259 | + out ('info', "\nDownloading $pp ($c{current}/$c{total})"); |
| 260 | + if ($o{threads}) { |
| 261 | + { # wait for the first download worker to tell us it's ready... |
| 262 | + lock $download_start; |
| 263 | + if (!defined($download_start)) { # if it hasn't already |
| 264 | + dbg ("Waiting for download worker broadcast"); |
| 265 | + cond_wait(\$download_start) until (defined($download_start) && $download_start == 0); |
| 266 | + } |
| 267 | + } |
| 268 | + { # signal download workers to start... |
| 269 | + lock $download_start; |
| 270 | + if(defined($download_start) && $download_start != 1) { # if we haven't already |
| 271 | + $download_start=1; |
| 272 | + dbg ("Broadcasting download loop ready"); |
| 273 | + cond_broadcast(\$download_start); |
| 274 | + } |
| 275 | + } |
| 276 | + while(!defined $p{$id}{worker_done} || !$p{$id}{worker_done}) { |
| 277 | + unbuffer_worker_out ($id); |
| 278 | + sleep 1; |
| 279 | + } |
| 280 | + unbuffer_worker_out ($id); |
| 281 | + } |
| 282 | + else { |
| 283 | + download_patch($pp); |
| 284 | + } |
| 285 | + } |
| 286 | + if ($o{install}) { |
| 287 | + out ('info', "\nInstalling $pp ($c{current}/$c{total})"); |
| 288 | + install_patch($pp); |
| 289 | + if (-x '/var/run/nopatch') { |
| 290 | + `/var/run/nopatch`; |
| 291 | + last |
| 292 | + } |
| 293 | + } |
| 294 | + if ($o{readme}) { |
| 295 | + my $rtmp=get_readme ($pp); |
| 296 | + ($rtmp) && (push (@rlist, $rtmp)); |
| 297 | + } |
| 298 | + ($o{download} || $o{install}) && out ('info', '-' x 78); |
| 299 | + } |
| 300 | + |
| 301 | + foreach my $worker (@workers) { |
| 302 | + dbg ("Waiting for worker"); |
| 303 | + $worker->join(); |
| 304 | + } |
| 305 | + |
| 306 | + if ($o{download} || $o{install}) { |
| 307 | + printf "Download Summary: %d total, %d successful, ", $c{total}, $c{dl}; |
| 308 | + printf "%d skipped, %d failed\n", $c{skipdl}, $c{faildl}; |
| 309 | + } |
| 310 | + if ($o{install}) { |
| 311 | + printf "Install Summary : %d total, %d successful, ", $c{total}, $c{inst}; |
| 312 | + printf "%d skipped, %d failed\n", $c{skipinst}, $c{failinst}; |
| 313 | + |
| 314 | + if ($c{p_ci}) { out ('info', "\nReconfiguration reboot required (init 6)") } |
| 315 | + elsif ($c{p_bi}) { out ('info', "\nReboot required (init 6)") } |
| 316 | + elsif ($c{p_c }) { out ('info', "\nReconfiguration reboot recommended (init 6)") } |
| 317 | + elsif ($c{p_b }) { out ('info', "\nReboot recommended (init 6)") } |
| 318 | + } |
| 319 | + if ($o{readme} && (@rlist)) { |
| 320 | + system ("$pager @rlist"); |
| 321 | + unlink (@rlist); |
| 322 | + } |
| 323 | +} |
| 324 | + |
| 325 | +sub expand_operands { |
| 326 | + my @tlist=@ARGV; my $again=1; my %fc; |
| 327 | + |
| 328 | + while ($again) { |
| 329 | + $again=0; @slist=(); |
| 330 | + foreach my $s (@tlist) { |
| 331 | + if ($s =~ /^(missingr?s?|installedr?s?|allr?s?|totalr?s?|unbundledr?s?|badr?s?)$/) { |
| 332 | + push (@slist, $s); |
| 333 | + } elsif ($s =~ /^(mr?s?|ir?s?|ar?s?|tr?s?|ur?s?|br?s?)$/) { |
| 334 | + push (@slist, $s); |
| 335 | + } elsif ($s =~ /^(\d{6}|\d{6}-\d{2})$/) { |
| 336 | + push (@slist, $s); |
| 337 | + } elsif ($s =~ /(\d{6}-\d{2})\.(zip|jar|tar\.Z|tar)$/) { |
| 338 | + push (@slist, $1); |
| 339 | + } elsif (-f $s) { |
| 340 | + if ($fc{$s}) { err ("Recursive file inclusion: $s") } else { $fc{$s}=1 } |
| 341 | + open (LIST, "<$s") || err ("Can't open $s ($!)"); |
| 342 | + while (<LIST>) { |
| 343 | + chomp; |
| 344 | + next unless $_; |
| 345 | + push (@slist, (split (/ /, $_))[0]); |
| 346 | + $again=1; |
| 347 | + } |
| 348 | + } else { |
| 349 | + err ("Unknown operand: $s"); |
| 350 | + } |
| 351 | + } |
| 352 | + @tlist=@slist; |
| 353 | + } |
| 354 | + dbg ("Expanded patch list: @slist"); |
| 355 | +} |
| 356 | + |
| 357 | +sub create_patch_list { |
| 358 | + # Put patches for patch utilities at the top of the list |
| 359 | + my @putil= (106125,106126,107171,107172,108987,108988,112951,114194,119254,119255); |
| 360 | + foreach my $id (@putil) { init_patch($id) } |
| 361 | + |
| 362 | + foreach my $id (@putil, sort keys %p) { |
| 363 | + add_patch_list ($id,0); |
| 364 | + } |
| 365 | +} |
| 366 | + |
| 367 | +sub add_patch_list { |
| 368 | + my $id=$_[0]; |
| 369 | + my $type=$_[1]; |
| 370 | + |
| 371 | + # Ignore patches which have been listed already. |
| 372 | + ($p{$id}{listed}) && return (0); |
| 373 | + |
| 374 | + $type=match_patch_list($id,$type); |
| 375 | + $type || return (0); |
| 376 | + |
| 377 | + if ($id eq "125547") { |
| 378 | + $p{$id}{requires}="122660-10"; |
| 379 | + $p{"122660"}{obs}=0; $p{"122660"}{obsoletedby}=""; |
| 380 | + $p{"124204"}{obs}=0; $p{"124204"}{obsoletedby}=""; |
| 381 | + $p{"118731"}{obs}=0; $p{"118731"}{obsoletedby}=""; |
| 382 | + } |
| 383 | + if ($id eq "125548") { |
| 384 | + $p{$id}{requires}="122661-08"; |
| 385 | + $p{"122661"}{obs}=0; $p{"122661"}{obsoletedby}=""; |
| 386 | + $p{"124205"}{obs}=0; $p{"124205"}{obsoletedby}=""; |
| 387 | + } |
| 388 | + |
| 389 | + if ($p{$id}{requires} ne '') { |
| 390 | + REQ: foreach my $r (split (/;/, $p{$id}{requires})) { |
| 391 | + # Fix required patches which were never released |
| 392 | + ($r eq "125077-02") && ($r="120011-09"); # 119757 |
| 393 | + ($r eq "125078-02") && ($r="120012-10"); # 119758 |
| 394 | + ($r eq "125486-01") && ($r="120011-14"); # 126206 |
| 395 | + ($r eq "125487-01") && ($r="120012-14"); # 126207 |
| 396 | + ($r eq "126677-02") && ($r="124628-03"); # 119534, 124630 |
| 397 | + ($r eq "126678-02") && ($r="124629-03"); # 119535, 124631 |
| 398 | + ($r eq "114431-03") && ($r="117172-17"); # 116473 |
| 399 | + |
| 400 | + my ($r_id, $r_rev)= split (/-/, $r); |
| 401 | + |
| 402 | + # If a required patch has been obsoleted by another patch, we |
| 403 | + # continue with the patch that obsoleted it. |
| 404 | + while ($p{$r_id}{obsoletedby} ne '') { |
| 405 | + my ($oby_id, $oby_rev)= split (/-/, $p{$r_id}{obsoletedby}); |
| 406 | + dbg ("$r_id-$r_rev required by $id: obsolete, replaced with $oby_id-$oby_rev"); |
| 407 | + ($r_id, $r_rev)= ($oby_id, $oby_rev); |
| 408 | + } |
| 409 | + # Check if patch requires itself |
| 410 | + if ($r_id eq $id) { |
| 411 | + dbg ("$r_id-$r_rev required by $id: patch requires itself"); |
| 412 | + next; |
| 413 | + } |
| 414 | + # Check if the required patch is in our database. Normally we should |
| 415 | + # stop with an error here, but maybe information in patchdiag.xref |
| 416 | + # is wrong and the patch will install without the missing required patch. |
| 417 | + if ($p{$r_id}{crev} eq "00") { |
| 418 | + dbg ("$r_id-$r_rev required by $id: unknown patch"); |
| 419 | + next; |
| 420 | + } |
| 421 | + # Ignore patches already in our list. |
| 422 | + if ($p{$r_id}{listed}) { |
| 423 | + dbg ("$r_id-$r_rev required by $id: already listed"); |
| 424 | + next; |
| 425 | + } |
| 426 | + # Ignore patches already installed. |
| 427 | + if ($p{$r_id}{irev} ge $r_rev) { |
| 428 | + dbg ("$r_id-$r_rev required by $id: already installed"); |
| 429 | + next; |
| 430 | + } |
| 431 | + # Check for circular patch dependencies. |
| 432 | + if ($p{$r_id}{requires} ne '') { |
| 433 | + foreach my $s (split (/;/, $p{$r_id}{requires})) { |
| 434 | + (my $s_id, my $s_rev)= split (/-/, $s); |
| 435 | + if (exists $rloop{"$r_id:$s_id"}) { |
| 436 | + dbg ("$r_id-$r_rev required by $id: Circular patch dependency"); |
| 437 | + next REQ; |
| 438 | + } |
| 439 | + $rloop{"$r_id:$s_id"} = 1; |
| 440 | + } |
| 441 | + } |
| 442 | + |
| 443 | + dbg ("$r_id-$r_rev required by $id"); |
| 444 | + if (!add_patch_list($r_id,$type)) { |
| 445 | + dbg ("$r_id-$r_rev required by $id: does not match"); |
| 446 | + } |
| 447 | + } |
| 448 | + } |
| 449 | + $p{$id}{listed}=1; |
| 450 | + push (@plist, $id); |
| 451 | + return (1); |
| 452 | +} |
| 453 | + |
| 454 | +sub match_patch_list { |
| 455 | + my $id=$_[0]; |
| 456 | + my $type=$_[1]; |
| 457 | + my $found; |
| 458 | + |
| 459 | + S: foreach my $s (@slist) { |
| 460 | + # Complete patch id with revision (123456-78) |
| 461 | + if ($s =~ /\d{6}-\d{2}/) { |
| 462 | + my ($s_id,$s_rev)= split(/-/,$s); |
| 463 | + if ($id eq $s_id) { |
| 464 | + if ($p{$id}{ignore} eq "00") { next } |
| 465 | + if ($p{$id}{ignore} ge $s_rev) { next } |
| 466 | + $p{$id}{prev}=$s_rev; |
| 467 | + return (1); |
| 468 | + } |
| 469 | + } |
| 470 | + # Incomplete patch id (123456) |
| 471 | + if ($s =~ /\d{6}/) { |
| 472 | + if ($id eq $s) { |
| 473 | + if ($p{$id}{ignore} eq "00") { next } |
| 474 | + if ($p{$id}{ignore} eq $p{$id}{crev}) { next } |
| 475 | + return (2); |
| 476 | + } |
| 477 | + if ($type == 2) { return (2); } |
| 478 | + } |
| 479 | + # installed or all |
| 480 | + if (($s =~ /^i/) || ($s =~ /^a/)) { |
| 481 | + if (!check_rs($s,$id)) { next; } |
| 482 | + |
| 483 | + # Check if patch is installed. |
| 484 | + if ($p{$id}{irev} ne '00') { return (3); } |
| 485 | + } |
| 486 | + # unbundled |
| 487 | + if ($s =~ /^u/) { |
| 488 | + # Check if patch is Unbundled and has an empy packages list. |
| 489 | + if (!(($p{$id}{os} eq "Unbundled") && ($p{$id}{pkgs} eq ""))) { next; } |
| 490 | + |
| 491 | + # Ignore obsolete and bad patches |
| 492 | + if ($p{$id}{obs} || $p{$id}{bad}) { next; } |
| 493 | + |
| 494 | + if (!check_rs($s,$id)) { next; } |
| 495 | + |
| 496 | + return (4); |
| 497 | + } |
| 498 | + # missing or all |
| 499 | + if (($s =~ /^m/) || ($s =~ /^a/)) { |
| 500 | + # Ignore obsolete and bad patches |
| 501 | + if ($p{$id}{obs} || $p{$id}{bad}) { next; } |
| 502 | + |
| 503 | + # Ignore patches which are installed in the current or higher revision |
| 504 | + if ($p{$id}{irev} ge $p{$id}{crev}) { next; } |
| 505 | + |
| 506 | + # Ignore patches for foreign architectures. |
| 507 | + $found=0; |
| 508 | + foreach my $j (split (/\;/, $p{$id}{archs})) { |
| 509 | + if (($j eq $u{arch}) || ($j eq "all") || ($j eq "Solaris") || ($j eq "$u{arch}.$u{model}")) { |
| 510 | + $found=1; last; |
| 511 | + } |
| 512 | + } |
| 513 | + if (!$found) { next; } |
| 514 | + |
| 515 | + # Ignore patches for packages that are not installed. |
| 516 | + $found=0; |
| 517 | + foreach my $j (split (/\;/, $p{$id}{pkgs})) { |
| 518 | + my ($package, $version)= split (/:/, $j); |
| 519 | + if ($pkgs{$package} && ($pkgs{$package} =~ /<$version>/)) { |
| 520 | + $found=1; last; |
| 521 | + } |
| 522 | + } |
| 523 | + if (!$found) { next; } |
| 524 | + |
| 525 | + if (!patch_apply_check($id)) { next; } |
| 526 | + if (!check_rs($s,$id) && ($type != 5)) { next; } |
| 527 | + |
| 528 | + return (5); |
| 529 | + } |
| 530 | + # Total set of patches |
| 531 | + if ($s =~ /^t/) { |
| 532 | + if ($p{$id}{crev} eq "00") { next; } |
| 533 | + if (!check_rs($s,$id)) { next; } |
| 534 | + |
| 535 | + return (6); |
| 536 | + } |
| 537 | + # Installed bad patches |
| 538 | + if ($s =~ /^b/) { |
| 539 | + if (!$p{$id}{ibad}) { next; } |
| 540 | + |
| 541 | + # Check if bad patch has been obsoleted by an installed patch |
| 542 | + my $oby_id= $id; my $oby_rev; |
| 543 | + while ($p{$oby_id}{obsoletedby} ne '') { |
| 544 | + ($oby_id, $oby_rev)= split (/-/, $p{$oby_id}{obsoletedby}); |
| 545 | + if ($p{$oby_id}{irev} ge $oby_rev) { next S; } |
| 546 | + } |
| 547 | + if (!check_rs($s,$id)) { next; } |
| 548 | + |
| 549 | + return (7); |
| 550 | + } |
| 551 | + } |
| 552 | + return (0); |
| 553 | +} |
| 554 | + |
| 555 | +sub check_rs { |
| 556 | + my $s=$_[0]; my $id=$_[1]; |
| 557 | + |
| 558 | + # Check that a "stop" patch hasn't been seen |
| 559 | + if ($stopreached) { return(0); } |
| 560 | + |
| 561 | + # Check that this isn't a "stop" patch |
| 562 | + if ($p{$id}{stop} eq "00") { $stopreached = 1; } |
| 563 | + if ($p{$id}{stop} eq $p{$id}{crev}) { $stopreached = 1; } |
| 564 | + |
| 565 | + # Check for R/S flags |
| 566 | + if ($s =~ /rs$/) { |
| 567 | + if (!($p{$id}{rec} || $p{$id}{recf} || $p{$id}{sec} || $p{$id}{secf})) { return(0); } |
| 568 | + } else { |
| 569 | + if (($s =~ /r$/) && (!$p{$id}{rec}) && (!$p{$id}{recf})) { return(0); } |
| 570 | + if (($s =~ /s$/) && (!$p{$id}{sec}) && (!$p{$id}{secf})) { return(0); } |
| 571 | + } |
| 572 | + # Ignore patches in the ignore list. |
| 573 | + if ($p{$id}{ignore} eq "00") { return 0 } |
| 574 | + if ($p{$id}{ignore} eq $p{$id}{crev}) { return 0 } |
| 575 | + |
| 576 | + # Check for minage, maxage and pattern |
| 577 | + if (($o{minage}) && (calculateage($p{$id}{reldate}) < $o{minage})) { return(0); } |
| 578 | + if (($o{maxage}) && (calculateage($p{$id}{reldate}) > $o{maxage})) { return(0); } |
| 579 | + if ($o{pattern}) { |
| 580 | + if ($o{pattern} =~ /^!/) { |
| 581 | + my $pattern= substr ($o{pattern}, 1); |
| 582 | + if ($p{$id}{synopsis} =~ /$pattern/) { return (0) } |
| 583 | + } else { |
| 584 | + if ($p{$id}{synopsis} !~ /$o{pattern}/) { return(0) } |
| 585 | + } |
| 586 | + } |
| 587 | + |
| 588 | + return(1); |
| 589 | +} |
| 590 | + |
| 591 | +sub download_patch { |
| 592 | + my $pp=$_[0]; |
| 593 | + my ($id, $rev)= split (/-/, $pp); |
| 594 | + |
| 595 | + lock_free($o{patchdir}, "download.$pp", 300) || err ("Another instance of pca is downloading $pp to $o{patchdir} right now"); |
| 596 | + |
| 597 | + # Check if patch exists |
| 598 | + if (-d "$o{patchdir}/$pp") { |
| 599 | + buffer_worker_out ($id, 'info', "Skipped (directory exists)"); $c{skipdl}++; return; |
| 600 | + } |
| 601 | + foreach my $ext ('zip','jar','tar.Z','tar') { |
| 602 | + if (-f "$o{patchdir}/$pp.$ext") { |
| 603 | + if (-s "$o{patchdir}/$pp.$ext") { |
| 604 | + buffer_worker_out ($id, 'info', "Skipped (file exists)"); $c{skipdl}++; return; |
| 605 | + } |
| 606 | + unlink "$o{patchdir}/$pp.$ext"; |
| 607 | + } |
| 608 | + } |
| 609 | + |
| 610 | + # Remember if we downloaded the patch for install only |
| 611 | + $o{download} || ($p{$id}{dfori}=1); |
| 612 | + |
| 613 | + (-w $o{patchdir}) || err ("Can't write to patch download directory $o{patchdir}"); |
| 614 | + |
| 615 | + lock_create($o{patchdir}, "download.$pp", 1) || err ("Another instance of pca is downloading $pp to $o{patchdir} right now"); |
| 616 | + |
| 617 | + # Try to get patch from local patch server |
| 618 | + if ($o{patchurl} =~ /^file:/) { |
| 619 | + buffer_worker_out ($id, 'info', "Trying $o{patchurl}"); |
| 620 | + my $path=$o{patchurl}; $path =~ s/^file://; |
| 621 | + foreach my $ext ('zip','jar','tar.Z','tar') { |
| 622 | + (-r "$path/$pp.$ext") && copy ("$path/$pp.$ext", "$o{patchdir}/$pp.$ext"); |
| 623 | + if (-s "$o{patchdir}/$pp.$ext") { |
| 624 | + buffer_worker_out ($id, 'info', "Done"); $c{dl}++; goto DONE; |
| 625 | + } |
| 626 | + unlink "$o{patchdir}/$pp.$ext"; |
| 627 | + } |
| 628 | + buffer_worker_out ($id, 'info', "Failed"); |
| 629 | + } |
| 630 | + # Without wget we can't download the patch |
| 631 | + if (!$o{wget}) { |
| 632 | + buffer_worker_out ($id, 'info', "Failed (can't find wget executable)"); goto FAIL; |
| 633 | + } |
| 634 | + # Try to get patch from local patch server with wget |
| 635 | + if ($o{patchurl} =~ /^http:|^https:|^ftp:/) { |
| 636 | + buffer_worker_out ($id, 'info', "Trying $o{patchurl}"); |
| 637 | + if ($o{patchurl} =~ /^http.*pca-proxy\.cgi/) { |
| 638 | + if (download("patch", $pp, "local", "$o{patchdir}/$pp.tmp", "")) { |
| 639 | + my $type=filetype("$o{patchdir}/$pp.tmp"); |
| 640 | + if ($type ne 'unknown') { |
| 641 | + rename ("$o{patchdir}/$pp.tmp", "$o{patchdir}/$pp.$type"); |
| 642 | + buffer_worker_out ($id, 'info', "Done"); $c{dl}++; goto DONE; |
| 643 | + } else { |
| 644 | + buffer_worker_out ($id, 'info', "Failed (unknown file type)"); |
| 645 | + } |
| 646 | + } else { |
| 647 | + buffer_worker_out ($id, 'info', "Failed"); |
| 648 | + } |
| 649 | + unlink "$o{patchdir}/$pp.tmp"; |
| 650 | + } elsif ($o{patchurl} =~ /^http:|^https:|^ftp:/) { |
| 651 | + foreach my $ext ('zip','jar','tar.Z','tar') { |
| 652 | + if (download("patch", "$pp.$ext", "local", "$o{patchdir}/$pp.$ext", "")) { |
| 653 | + buffer_worker_out ($id, 'info', "Done"); $c{dl}++; goto DONE; |
| 654 | + } |
| 655 | + unlink "$o{patchdir}/$pp.$ext"; |
| 656 | + } |
| 657 | + buffer_worker_out ($id, 'info', "Failed"); |
| 658 | + } |
| 659 | + } |
| 660 | + # Try download from restricted patch server, if the user provided |
| 661 | + # Sun Online Account data |
| 662 | + if (checksoa()) { |
| 663 | + my $try=1; |
| 664 | + while ($try <= $o{dltries} ) { |
| 665 | + buffer_worker_out ($id, 'info', "Trying $o{ssprot}://$o{sshost}/ ($try/$o{dltries})"); |
| 666 | + if (download("patch", $pp, "sunsolve", "$o{patchdir}/$pp.tmp", "")) { |
| 667 | + my $type=filetype("$o{patchdir}/$pp.tmp"); |
| 668 | + if ($type ne 'unknown') { |
| 669 | + rename ("$o{patchdir}/$pp.tmp", "$o{patchdir}/$pp.$type"); |
| 670 | + buffer_worker_out ($id, 'info', "Done"); $c{dl}++; goto DONE; |
| 671 | + } else { |
| 672 | + buffer_worker_out ($id, 'info', "Failed (unknown file type)"); |
| 673 | + } |
| 674 | + } else { |
| 675 | + buffer_worker_out ($id, 'info', "Failed"); |
| 676 | + } |
| 677 | + unlink "$o{patchdir}/$pp.tmp"; |
| 678 | + $try++; if ($try <= $o{dltries}) { sleep ($try*2) } |
| 679 | + } |
| 680 | + } else { |
| 681 | + buffer_worker_out ($id, 'info', "Failed (no Sun Online Account data)"); |
| 682 | + } |
| 683 | +FAIL: |
| 684 | + buffer_worker_out ($id, 'info', "Failed (patch not found)"); |
| 685 | + $c{faildl}++; |
| 686 | +DONE: |
| 687 | + lock_remove($o{patchdir}, "download.$pp"); |
| 688 | +} |
| 689 | + |
| 690 | +sub download { |
| 691 | + my $what=$_[0]; my $pp=$_[1]; my $src=$_[2]; my $dstf=$_[3]; my $dstd=$_[4]; |
| 692 | + |
| 693 | + my %urls=( |
| 694 | + "pca:pcaurl", "$o{pcaurl}pca", |
| 695 | + "xref:local", "$o{xrefurl}patchdiag.xref", |
| 696 | + "xref:sunsolve", "$o{ssprot}://$o{sshost}/patchdiag.xref", |
| 697 | + "readme:local", "$o{patchurl}README.$pp", |
| 698 | + "readme:sunsolve", "$o{ssprot}://$o{sshost}/pdownload.do?target=$pp&method=r", |
| 699 | + "patch:local", "$o{patchurl}$pp", |
| 700 | + "patch:sunsolve", "$o{ssprot}://$o{sshost}/pdownload.do?target=$pp&method=h" |
| 701 | + ); |
| 702 | + my $cmd="$o{wget}"; my $url; |
| 703 | + |
| 704 | + if (($o{debug}) && ($o{threads} > 1)) { $cmd .= " -nv" } |
| 705 | + if (!$o{debug}) { $cmd .= " -q" } |
| 706 | + |
| 707 | + $url=$urls{"$what:$src"}; |
| 708 | + if (($o{force}) && ($url =~ /pca-proxy\.cgi/)) { $url .= ":force" } |
| 709 | + $cmd .= " \"$url\""; |
| 710 | + |
| 711 | + if ($o{wgetproxy}) { $cmd .= " --execute http_proxy=$o{wgetproxy}" } |
| 712 | + if (($what eq "xref") && ($src eq "sunsolve") && ($o{nocache})) { $cmd .= " --execute cache=off" } |
| 713 | + if ((($url =~ /https:\/\/www.par.univie.ac.at\//) || ($url =~ /https:\/\/sunsolve.sun.com\//)) && ($wgetv >= 11000)) { $cmd .= " --ca-certificate=$0" } |
| 714 | + if (($what eq "patch") && ($url =~ /pca-proxy\.cgi/)) { $cmd .= " --timeout 3600" } |
| 715 | + if ((($what eq "patch") || ($what eq "readme")) && ($src eq "sunsolve")) { |
| 716 | + $cmd .= " --header=\"Authorization: Basic " . base64("$a{user}:$a{passwd}") . "\""; |
| 717 | + } |
| 718 | + |
| 719 | + if ($dstf) { |
| 720 | + $cmd .= " -O $dstf"; |
| 721 | + if ($what eq "patch") { $p{$pp}{dlfile}="$dstf" } else { $dlfile="$dstf" } |
| 722 | + } |
| 723 | + if ($dstd) { |
| 724 | + $cmd = "cd $dstd; " . $cmd . " -N"; |
| 725 | + } |
| 726 | + $o{debug} && $o{proxy} && ($cmd .= " >>$o{dbgfile} 2>&1"); |
| 727 | + dbg ($cmd); `$cmd`; |
| 728 | + if ($what eq "patch") { $p{$pp}{dlfile}="" } else { $dlfile="" } |
| 729 | + |
| 730 | + if (!$? && ($dstd)) { return 1 } |
| 731 | + if (!$? && ($dstf) && (-s $dstf)) { return 1 } |
| 732 | + return 0; |
| 733 | +} |
| 734 | + |
| 735 | +sub filetype { |
| 736 | + my $fname=$_[0]; my $buffer; |
| 737 | + |
| 738 | + open (F, "< $fname") || err ("Can't open $fname ($!)"); |
| 739 | + read F, $buffer, 1024; |
| 740 | + close (F); |
| 741 | + |
| 742 | + if (substr($buffer, 257, 5) eq "ustar") { return ('tar') } |
| 743 | + if (substr($buffer, 0, 2) eq "\037\235") { return ('tar.Z') } |
| 744 | + if (substr($buffer, 0, 4) eq "PK\003\004") { |
| 745 | + `$unzip -l $fname META-INF/manifest.mf 2>&1`; |
| 746 | + if ($?) { return ('zip') } else { return ('jar') } |
| 747 | + } |
| 748 | + |
| 749 | + dbg ("Unknown Filetype: $fname"); |
| 750 | + return ('unknown'); |
| 751 | +} |
| 752 | + |
| 753 | +sub install_patch { |
| 754 | + my $pp=$_[0]; |
| 755 | + my ($id, $rev)= split (/-/, $pp); |
| 756 | + my $output; |
| 757 | + my $dfile=''; |
| 758 | + my $opt=''; |
| 759 | + |
| 760 | + $patchxdir= "$o{tmpdir}/pca." . time() . $$; |
| 761 | + mkdir $patchxdir,0755 || err ("Can't create temporary directory $patchxdir ($!)"); |
| 762 | + |
| 763 | + if (-d "$o{patchdir}/$pp") { |
| 764 | + $?= !symlink ("$o{patchdir}/$pp", "$patchxdir/$pp"); |
| 765 | + } elsif (-f "$o{patchdir}/$pp.zip") { |
| 766 | + out ('info', "Unzipping patch"); |
| 767 | + `$unzip -n $o{patchdir}/$pp.zip -d $patchxdir </dev/null 2>&1`; |
| 768 | + $p{$id}{dfori} && ($dfile= "$o{patchdir}/$pp.zip") |
| 769 | + } elsif (-f "$o{patchdir}/$pp.jar") { |
| 770 | + out ('info', "Unjarring patch"); |
| 771 | + `$unzip -n $o{patchdir}/$pp.jar -d $patchxdir </dev/null 2>&1`; |
| 772 | + $p{$id}{dfori} && ($dfile= "$o{patchdir}/$pp.jar") |
| 773 | + } elsif (-f "$o{patchdir}/$pp.tar.Z") { |
| 774 | + out ('info', "Uncompressing patch"); |
| 775 | + `cd $patchxdir; $uncompress -c $o{patchdir}/$pp.tar.Z | $tar xf -`; |
| 776 | + $p{$id}{dfori} && ($dfile= "$o{patchdir}/$pp.tar.Z") |
| 777 | + } elsif (-f "$o{patchdir}/$pp.tar") { |
| 778 | + out ('info', "Untarring patch"); |
| 779 | + `cd $patchxdir; $tar xf $o{patchdir}/$pp.tar`; |
| 780 | + $p{$id}{dfori} && ($dfile= "$o{patchdir}/$pp.tar") |
| 781 | + } else { |
| 782 | + out ('info', "Failed (missing patch file)"); |
| 783 | + rmdir $patchxdir; $patchxdir=""; |
| 784 | + $c{failinst}++; return; |
| 785 | + } |
| 786 | + if (($?) || (! -d "$patchxdir/$pp")) { |
| 787 | + out ('info', "Failed"); |
| 788 | + rmtree ($patchxdir); $patchxdir=""; |
| 789 | + $c{failinst}++; return; |
| 790 | + } |
| 791 | + my $readme= "$patchxdir/$pp/README.$pp"; |
| 792 | + my $patchinfo= "$patchxdir/$pp/patchinfo"; |
| 793 | + |
| 794 | + if ($o{safe}) { |
| 795 | + out ('info', "Checking files for safe patch installation"); |
| 796 | + if (!verify_files($id, $readme)) { |
| 797 | + rmtree ($patchxdir); $patchxdir=""; |
| 798 | + $c{failinst}++; return; |
| 799 | + } |
| 800 | + } |
| 801 | + |
| 802 | + # Do we need a reboot? |
| 803 | + my $p_b=0; my $p_bi=0; my $p_c=0; my $p_ci=0; |
| 804 | + if (-f $patchinfo) { |
| 805 | + open(PATCHINFO,$patchinfo) || err ("Can't open $patchinfo ($!)"); |
| 806 | + dbg ("Checking for reboot/reconfig in patchinfo"); |
| 807 | + while (<PATCHINFO>) { |
| 808 | + if (/PATCH_PROPERTIES=.*reconfigimmediate/) { $p_ci=1; last } |
| 809 | + if (/PATCH_PROPERTIES=.*rebootimmediate/) { $p_bi=1; last } |
| 810 | + if (/PATCH_PROPERTIES=.*reconfigafter/) { $p_c=1; last } |
| 811 | + if (/PATCH_PROPERTIES=.*rebootafter/) { $p_b=1; last } |
| 812 | + } |
| 813 | + close PATCHINFO; |
| 814 | + } elsif (-f $readme) { |
| 815 | + open(README,$readme) || err ("Can't open $readme ($!)"); |
| 816 | + dbg ("Checking for reboot/reconfig in README"); |
| 817 | + while(<README>) { |
| 818 | + if (/Reconfig.*immediate.*after.*install/) { $p_ci=1; last } |
| 819 | + if (/Reboot.*immediate.*after.*install/) { $p_bi=1; last } |
| 820 | + if (/Reconfig.*after.*install/) { $p_c=1; last } |
| 821 | + if (/Reboot.*after.*install/) { $p_b=1; last } |
| 822 | + } |
| 823 | + close README; |
| 824 | + } |
| 825 | + |
| 826 | + # If the patchadd command doesn't exist, try installpatch, which |
| 827 | + # comes with patches for Solaris <= 2.5.1. |
| 828 | + (-x $o{patchadd}) || ($o{patchadd}="$patchxdir/$pp/installpatch"); |
| 829 | + (-x $o{patchadd}) || err ("Can't execute patchadd/installpatch"); |
| 830 | + |
| 831 | + # Sun Studio 11 patches on Solaris 10 must be installed with -G |
| 832 | + # Patches 119254-34 and 119255-34 fix this in patchadd |
| 833 | + my ($major, $minor) = split (/\./, $u{osrel}); |
| 834 | + if (($minor == 10) && ($p{$id}{synopsis} =~ /^Sun Studio 11/) && (!$o{currentzone})) { |
| 835 | + if (!($p{119254}{irev} ge '34') && !($p{119255}{irev} ge '34')) { |
| 836 | + dbg ("Adding -G to patchadd for Sun Studio 11 on Solaris 10"); |
| 837 | + $opt .= "-G "; |
| 838 | + } |
| 839 | + } |
| 840 | + # Ignore currentzone option on Solaris <= 9 |
| 841 | + ($minor <= 9) && ($o{currentzone}=0); |
| 842 | + |
| 843 | + if ($o{noreboot} && ($p_ci || $p_bi || $p_c || $p_b)) { |
| 844 | + out ('info', "Skipping patchadd (noreboot)"); $c{skipinst}++; |
| 845 | + } elsif ($o{pretend}) { |
| 846 | + out ('info', "Skipping patchadd (pretend)"); $c{skipinst}++; |
| 847 | + } else { |
| 848 | + lock_create($o{tmpdir}, "install", 1) || err ("Another instance of pca is installing patches right now"); |
| 849 | + $o{currentzone} && ($opt .= "-G "); |
| 850 | + if (($o{nobackup} =~ /all/) || ($p{$id}{nobackup} eq "00") || ($p{$id}{nobackup} eq $p{$id}{crev})) { $opt .= "-d " } |
| 851 | + $o{backdir} && ($opt .= "-B $o{backdir} "); |
| 852 | + out ('info', "Running patchadd"); |
| 853 | + dbg ("Starting patchadd at " . localtime); |
| 854 | + dbg ("$o{patchadd} $o{root} $opt $patchxdir/$pp"); |
| 855 | + $SIG{INT}='IGNORE'; |
| 856 | + $output=`$o{patchadd} $o{root} $opt $patchxdir/$pp </dev/null 2>&1`; |
| 857 | + $SIG{INT}=\&handler; |
| 858 | + my $rc=$?; |
| 859 | + lock_remove($o{tmpdir}, "install"); |
| 860 | + if ($rc) { |
| 861 | + out ('info', "\n$output"); |
| 862 | + $rc /= 256; out ('info', "Failed (exit code $rc)\n$!"); |
| 863 | + rmtree ($patchxdir); $patchxdir=""; |
| 864 | + log_msg("Failed to install patch $pp ($p{$id}{synopsis}) rc=$rc"); |
| 865 | + $c{failinst}++; return; |
| 866 | + } |
| 867 | + dbg ("\n$output"); |
| 868 | + out ('info', "Done"); $c{inst}++; |
| 869 | + $dfile && unlink ($dfile); |
| 870 | + log_msg("Installed patch $pp ($p{$id}{synopsis})"); |
| 871 | + if ($p_ci || $p_c) { |
| 872 | + my $r=''; if ($o{root}) { $r=$o{root}; $r =~ s/-R // } |
| 873 | + if (! -f "$r/reconfigure") { |
| 874 | + out ('info', "Creating $r/reconfigure"); |
| 875 | + open (F, ">$r/reconfigure"); close (F); |
| 876 | + } |
| 877 | + } |
| 878 | + } |
| 879 | + if ($p_ci) { out ('info', "Reconfig required"); $o{noreboot} || $c{p_ci}++ } |
| 880 | + elsif ($p_bi) { out ('info', "Reboot required"); $o{noreboot} || $c{p_bi}++ } |
| 881 | + elsif ($p_c ) { out ('info', "Reconfig recommended"); $o{noreboot} || $c{p_c}++ } |
| 882 | + elsif ($p_b ) { out ('info', "Reboot recommended"); $o{noreboot} || $c{p_b}++ } |
| 883 | + rmtree ($patchxdir); $patchxdir=""; |
| 884 | +} |
| 885 | + |
| 886 | +sub proxy { |
| 887 | + my $f=$o{proxy}; |
| 888 | + my $odir; |
| 889 | + |
| 890 | + dbg ("Requested file: $f"); |
| 891 | + if ($f =~ /^patchdiag.xref$/) { |
| 892 | + $o{xrefown}=1; $odir=$o{xrefdir}; |
| 893 | + if ($o{pforce}) { unlink ("$odir/$f") } |
| 894 | + get_current_xref(); |
| 895 | + } |
| 896 | + if ($f =~ /^README\.\d{6}-\d{2}$/) { |
| 897 | + my $pp=$f; $pp =~ s/^.*(\d{6}-\d{2}).*$/$1/; $odir=$o{patchdir}; |
| 898 | + if ($o{pforce}) { unlink ("$odir/$f") } |
| 899 | + if (! -f "$odir/$f") { |
| 900 | + my $rtmp=get_readme ($pp); |
| 901 | + if ($rtmp) { |
| 902 | + copy ($rtmp, "$odir/$f"); |
| 903 | + unlink ($rtmp); |
| 904 | + } |
| 905 | + } |
| 906 | + } |
| 907 | + # Deprecated |
| 908 | + if ($f =~ /^\d{6}-\d{2}\.(zip|jar|tar|tar\.Z)$/) { |
| 909 | + my $pp=$f; $pp =~ s/^.*(\d{6}-\d{2}).*$/$1/; $odir=$o{patchdir}; |
| 910 | + if ($o{pforce}) { unlink ("$odir/$f") } |
| 911 | + download_patch($pp); |
| 912 | + } |
| 913 | + if ($f =~ /^\d{6}-\d{2}$/) { |
| 914 | + $odir=$o{patchdir}; |
| 915 | + if ($o{pforce}) { unlink ("$odir/$f.zip", "$odir/$f.jar", "$odir/$f.tar", "$odir/$f.tar.Z") } |
| 916 | + download_patch($f); |
| 917 | + (-f "$odir/$f.zip") && ($f="$f.zip"); |
| 918 | + (-f "$odir/$f.jar") && ($f="$f.jar"); |
| 919 | + (-f "$odir/$f.tar") && ($f="$f.tar"); |
| 920 | + (-f "$odir/$f.tar.Z") && ($f="$f.tar.Z"); |
| 921 | + } |
| 922 | + if ($f =~ /^pca$/) { |
| 923 | + $odir=$o{patchdir}; |
| 924 | + if ($o{pforce}) { unlink ("$odir/$f") } |
| 925 | + if ($o{pcaurl} =~ /^http.*pca-proxy\.cgi/) { |
| 926 | + download('pca', '', 'pcaurl', "$odir/pca", ""); |
| 927 | + } else { |
| 928 | + download('pca', '', 'pcaurl', "", $odir); |
| 929 | + } |
| 930 | + } |
| 931 | + |
| 932 | + if (-f "$odir/$f") { |
| 933 | + ($f =~ /patchdiag.xref/) && print "Content-type: text/plain\n"; |
| 934 | + ($f =~ /README/) && print "Content-type: text/plain\n"; |
| 935 | + ($f =~ /\.zip$/) && print "Content-type: application/zip\n"; |
| 936 | + ($f =~ /\.jar$/) && print "Content-type: application/zip\n"; |
| 937 | + ($f =~ /\.tar$/) && print "Content-type: application/x-tar\n"; |
| 938 | + ($f =~ /\.tar.Z$/) && print "Content-type: application/x-compress\n"; |
| 939 | + ($f =~ /^pca$/) && print "Content-type: text/plain\n"; |
| 940 | + |
| 941 | + my $size=(stat("$odir/$f"))[7]; |
| 942 | + print "Content-length: $size\n\n"; |
| 943 | + |
| 944 | + open (F, "<$odir/$f"); read (F, my $content, $size); close (F); |
| 945 | + print $content; |
| 946 | + } else { |
| 947 | + err ("$f not found"); |
| 948 | + } |
| 949 | + exit 0; |
| 950 | +} |
| 951 | + |
| 952 | +sub checksoa { |
| 953 | + lock %a; # prevent simultaneous access to checksoa() if multithreaded |
| 954 | + if(!$a{transcribed}) { |
| 955 | + $a{user}=$o{user}; |
| 956 | + $a{passwd}=$o{passwd}; |
| 957 | + $a{askauth}=$o{askauth}; |
| 958 | + $a{transcribed}=1; |
| 959 | + } |
| 960 | + # Check if we already asked for user/passwd |
| 961 | + if ($a{askauth} eq 'asked') { |
| 962 | + if ($a{user} && $a{passwd}) { return (1) } else { return (0) } |
| 963 | + } |
| 964 | + # If askauth is set, ask for user |
| 965 | + my $uask=0; |
| 966 | + if ($a{askauth}) { |
| 967 | + print "\nPlease enter Sun Online Account User: "; |
| 968 | + chomp($a{user} = <STDIN>); |
| 969 | + $a{askauth}= 'asked'; $uask=1; |
| 970 | + } |
| 971 | + # If askauth or user (but not passwd) is set, ask for passwd |
| 972 | + if ($a{askauth} || ($a{user} && !$a{passwd})) { |
| 973 | + system "stty -echo"; $sttyset=1; |
| 974 | + $uask || print "\n"; |
| 975 | + print "Please enter Sun Online Account Password"; |
| 976 | + if ($a{askauth}) { print ": " } else { print " for $a{user}: " } |
| 977 | + chomp($a{passwd} = <STDIN>); |
| 978 | + print "\n\n"; |
| 979 | + system "stty echo"; $sttyset=0; |
| 980 | + $a{askauth}= 'asked'; |
| 981 | + } |
| 982 | + if ($a{user} && $a{passwd}) { return (1) } else { return (0) } |
| 983 | +} |
| 984 | + |
| 985 | +sub check_prerequisites { |
| 986 | + # Must be root to install patches |
| 987 | + if ($o{install} && ($< != 0) && !$o{pretend}) { |
| 988 | + err ("You must be root to install patches"); |
| 989 | + } |
| 990 | + if ($o{install} && $o{safe} && !$o{proxy} && ($< != 0)) { |
| 991 | + err ("You must be root to use safe mode"); |
| 992 | + } |
| 993 | + |
| 994 | + # Set umask (esp. for patchxdir) |
| 995 | + umask (0022); |
| 996 | + |
| 997 | + # Check for wget executable |
| 998 | + my $found=''; |
| 999 | + foreach my $i (split (/ /, $o{wget})) { |
| 1000 | + if (-x $i) { |
| 1001 | + $found= $i; |
| 1002 | + open (W, "$found --version |"); my $v=<W>; close (W); chomp $v; |
| 1003 | + $v =~ s/^GNU Wget ([\d\.]*).*$/$1/; my ($v1, $v2, $v3) = split (/\./, $v); |
| 1004 | + $wgetv=$v1*10000 + $v2*100; $v3 && ($wgetv += $v3); |
| 1005 | + dbg ("Using $found ($v, $wgetv)"); |
| 1006 | + last; |
| 1007 | + } |
| 1008 | + } |
| 1009 | + $o{wget}=$found; |
| 1010 | + |
| 1011 | + # Get patchdiag.xref location |
| 1012 | + $input{xref}="$o{xrefdir}/patchdiag.xref"; |
| 1013 | + |
| 1014 | + # Check patch download directory |
| 1015 | + (-d $o{patchdir}) || err ("Can't find patch directory $o{patchdir}"); |
| 1016 | + |
| 1017 | + # Check for pager |
| 1018 | + $ENV{PAGER} && ($pager=$ENV{PAGER}); |
| 1019 | + |
| 1020 | + # Check for valid prefix in $fromfiles and set input files/commands |
| 1021 | + if ($o{fromfiles}) { |
| 1022 | + if (-f "$o{fromfiles}/sysconfig/uname-a.out") { |
| 1023 | + $input{pkginfo}= "<$o{fromfiles}/patch+pkg/pkginfo-l.out"; |
| 1024 | + $input{showrev}= "<$o{fromfiles}/patch+pkg/showrev-p.out"; |
| 1025 | + $input{uname} = "<$o{fromfiles}/sysconfig/uname-a.out"; |
| 1026 | + } elsif (-f "$o{fromfiles}uname.out") { |
| 1027 | + $input{pkginfo}= "<$o{fromfiles}pkginfo.out"; |
| 1028 | + $input{showrev}= "<$o{fromfiles}showrev.out"; |
| 1029 | + $input{uname} = "<$o{fromfiles}uname.out"; |
| 1030 | + } elsif (-f "$o{fromfiles}/uname.out") { |
| 1031 | + $input{pkginfo}= "<$o{fromfiles}/pkginfo.out"; |
| 1032 | + $input{showrev}= "<$o{fromfiles}/showrev.out"; |
| 1033 | + $input{uname} = "<$o{fromfiles}/uname.out"; |
| 1034 | + } else { |
| 1035 | + err ("Can't find pkginfo/showrev/uname output with prefix $o{fromfiles}"); |
| 1036 | + } |
| 1037 | + dbg ("Using $o{fromfiles} as prefix to read .out files"); |
| 1038 | + } else { |
| 1039 | + $input{pkginfo}= "$pkginfo -x $o{root} |"; |
| 1040 | + $input{uname} = "$uname -a |"; |
| 1041 | + } |
| 1042 | + |
| 1043 | + # Set default locale for forks |
| 1044 | + $ENV{LC_ALL}='C'; |
| 1045 | + |
| 1046 | + # Make sure that any request to thread is sane |
| 1047 | + if (!$Config{useithreads} || $o{threads} < 2 || !($o{download} || $o{install})) { |
| 1048 | + dbg ("Prerequisites for threads not met, setting threads to 0"); |
| 1049 | + $o{threads} = 0; |
| 1050 | + } |
| 1051 | +} |
| 1052 | + |
| 1053 | +sub import_threads { |
| 1054 | + return unless ($o{threads} > 1); |
| 1055 | + |
| 1056 | + eval { require threads; require threads::shared; require Thread::Queue; }; |
| 1057 | + if (!$@) { |
| 1058 | + dbg ("Thread modules passed require, importing"); |
| 1059 | + BEGIN { $^W = 0 } |
| 1060 | + threads->import; |
| 1061 | + BEGIN { $^W = 1 } |
| 1062 | + threads::shared->import; |
| 1063 | + Thread::Queue->import; |
| 1064 | + $queue = new Thread::Queue; |
| 1065 | + share(\%a); |
| 1066 | + share(\%c); |
| 1067 | + share(\$download_start); |
| 1068 | + share(\%locks); |
| 1069 | + } |
| 1070 | + else { |
| 1071 | + dbg ("Thread modules did not pass require"); |
| 1072 | + $o{threads} = 0; |
| 1073 | + } |
| 1074 | +} |
| 1075 | + |
| 1076 | +sub verify_files { |
| 1077 | + my $id=$_[0]; my $readme=$_[1]; my @files=(); my %wl; |
| 1078 | + |
| 1079 | + # All |
| 1080 | + $wl{all}="/etc/name_to_major /etc/driver_aliases /etc/driver_classes /etc/minor_perm /etc/security/exec_attr"; |
| 1081 | + # 7/SPARC |
| 1082 | + $wl{106541}="/etc/devlink.tab /etc/rmmount.conf /etc/syslog.conf /etc/vold.conf"; |
| 1083 | + $wl{106857}="/usr/openwin/share/locale/C/props/basic_setting"; |
| 1084 | + $wl{106978}="/etc/nsswitch.conf"; |
| 1085 | + $wl{107589}="/etc/default/kbd"; |
| 1086 | + $wl{107684}="/etc/inet/services /etc/mail/main.cf /etc/mail/subsidiary.cf"; |
| 1087 | + $wl{107738}="/usr/openwin/lib/locale/compose.dir /usr/openwin/lib/locale/locale.alias /usr/openwin/lib/locale/locale.dir"; |
| 1088 | + $wl{108800}="/etc/inet/inetd.conf /etc/init.d/cachefs.daemon"; |
| 1089 | + # 8/SPARC |
| 1090 | + $wl{108725}="/kernel/drv/st.conf"; |
| 1091 | + $wl{108968}="/etc/rmmount.conf /etc/vold.conf"; |
| 1092 | + $wl{108999}="/etc/pam.conf"; |
| 1093 | + $wl{109077}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1094 | + $wl{109134}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1095 | + $wl{109695}="/etc/smartcard/opencard.properties"; |
| 1096 | + $wl{109766}="/usr/openwin/lib/locale/ja/X11/fonts/TT/fonts.alias"; |
| 1097 | + $wl{109887}="/etc/smartcard/ocf.classpath"; |
| 1098 | + $wl{110369}="/etc/iu.ap"; |
| 1099 | + $wl{110386}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1100 | + $wl{110615}="/etc/mail/main.cf /etc/mail/subsidiary.cf"; |
| 1101 | + $wl{110896}="/etc/inet/inetd.conf"; |
| 1102 | + $wl{112438}="/etc/devlink.tab"; |
| 1103 | + $wl{112663}="/usr/openwin/server/etc/OWconfig"; |
| 1104 | + $wl{114542}="/usr/openwin/lib/X11/fonts/TrueType/ttmap/ttmaps.dir /usr/openwin/lib/X11/fonts/encodings/encodings.dir"; |
| 1105 | + $wl{116973}="/etc/apache/mime.types"; |
| 1106 | + $wl{117518}="/usr/openwin/lib/X11/fonts/F3bitmaps/fonts.dir"; |
| 1107 | + $wl{128624}="/etc/default/login /etc/nsswitch.conf /etc/pam.conf"; |
| 1108 | + # 9/SPARC |
| 1109 | + $wl{112233}="/etc/iu.ap"; |
| 1110 | + $wl{112874}="/etc/name_to_sysnum /etc/security/crypt.conf /etc/security/policy.conf"; |
| 1111 | + $wl{112908}="/etc/krb5/krb5.conf"; |
| 1112 | + $wl{112954}="/kernel/drv/uata.conf"; |
| 1113 | + $wl{113073}="/etc/inet/inetd.conf"; |
| 1114 | + $wl{113085}="/usr/openwin/lib/X11/fonts/TrueType/ttmap/ttmaps.dir /usr/openwin/lib/X11/fonts/encodings/encodings.dir"; |
| 1115 | + $wl{113096}="/usr/openwin/server/etc/OWconfig"; |
| 1116 | + $wl{113277}="/kernel/drv/st.conf /kernel/drv/sd.conf"; |
| 1117 | + $wl{113471}="/usr/bin/cputrack"; |
| 1118 | + $wl{113575}="/etc/mail/main.cf /etc/mail/subsidiary.cf"; |
| 1119 | + $wl{114320}="/usr/openwin/server/etc/OWconfig"; |
| 1120 | + $wl{114352}="/etc/inet/inetd.conf"; |
| 1121 | + $wl{123184}="/usr/openwin/lib/X11/fonts/TrueType/ttmap/ttmaps.dir /usr/openwin/lib/X11/fonts/encodings/encodings.dir"; |
| 1122 | + # 9/x86 |
| 1123 | + $wl{114137}="/etc/mail/main.cf /etc/mail/subsidiary.cf"; |
| 1124 | + $wl{114353}="/etc/inet/inetd.conf"; |
| 1125 | + $wl{115168}="/etc/krb5/krb5.conf"; |
| 1126 | + $wl{122300}="/etc/rc0.d/K05volmgt /etc/rc1.d/K05volmgt /etc/rc2.d/K05volmgt /etc/rc3.d/S81volmgt /etc/rcS.d/K05volmgt /etc/security/audit_class /etc/security/audit_event"; |
| 1127 | + # 10/SPARC |
| 1128 | + $wl{116298}="/usr/bin/wscompile /usr/bin/wsdeploy"; |
| 1129 | + $wl{118666}="/etc/.java/.systemPrefs/.system.lock /etc/.java/.systemPrefs/.systemRootModFile"; |
| 1130 | + $wl{118717}="/usr/openwin/server/etc/OWconfig"; |
| 1131 | + $wl{118833}="/etc/logindevperm /etc/security/prof_attr /etc/vold.conf /etc/security/auth_attr"; |
| 1132 | + $wl{119090}="/etc/ima.conf /kernel/drv/iscsi.conf"; |
| 1133 | + $wl{119130}="/kernel/drv/fp.conf /kernel/drv/qlc.conf"; |
| 1134 | + $wl{119252}="/etc/default/kbd /etc/default/nfs"; |
| 1135 | + $wl{119313}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1136 | + $wl{119757}="/etc/inet/services"; |
| 1137 | + $wl{120011}="/etc/inet/hosts /etc/inet/ipnodes /etc/inet/services /etc/nscd.conf /etc/security/auth_attr /etc/security/prof_attr /etc/default/dhcpagent /etc/security/device_policy /etc/iu.ap"; |
| 1138 | + $wl{120185}="/opt/staroffice8/share/config/javasettingsunopkginstall.xml"; |
| 1139 | + $wl{120222}="/kernel/drv/emlxs.conf"; |
| 1140 | + $wl{120346}="/etc/hba.conf"; |
| 1141 | + $wl{120410}="/etc/gtk-2.0/gtk.immodules /etc/sparcv9/gtk-2.0/gtk.immodules"; |
| 1142 | + $wl{120460}="/etc/gtk-2.0/gtk.immodules /etc/sparcv9/gtk-2.0/gtk.immodules"; |
| 1143 | + $wl{121430}="/etc/default/lu"; |
| 1144 | + $wl{122212}="/etc/gconf/gconf.xml.defaults/apps/panel/default_setup/general/%gconf.xml"; |
| 1145 | + $wl{124393}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1146 | + $wl{125166}="/kernel/drv/qlc.conf"; |
| 1147 | + $wl{127127}="/etc/krb5/krb5.conf /etc/logadm.conf /etc/pam.conf /etc/security/audit_warn /etc/security/auth_attr /etc/security/prof_attr /etc/shadow /etc/user_attr /kernel/drv/mpt.conf"; |
| 1148 | + $wl{127755}="/etc/logadm.conf"; |
| 1149 | + $wl{137093}="/etc/logindevperm"; |
| 1150 | + $wl{137274}="/etc/mnttab"; |
| 1151 | + # 10/x86 |
| 1152 | + $wl{118855}="/etc/logindevperm /etc/security/prof_attr /etc/vold.conf /lib/libc.so.1 /etc/security/device_policy /etc/ipf/pfil.ap /boot/solaris/devicedb/master"; |
| 1153 | + $wl{119091}="/etc/ima.conf /kernel/drv/iscsi.conf"; |
| 1154 | + $wl{119131}="/kernel/drv/fp.conf /kernel/drv/qlc.conf"; |
| 1155 | + $wl{119253}="/etc/default/kbd /etc/default/nfs"; |
| 1156 | + $wl{119314}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1157 | + $wl{119758}="/etc/inet/services"; |
| 1158 | + $wl{120012}="/boot/solaris/bootenv.rc /boot/solaris/devicedb/master /etc/default/dhcpagent /etc/inet/hosts /etc/inet/ipnodes /etc/inet/services /etc/nscd.conf /etc/security/auth_attr /etc/security/device_policy /etc/security/prof_attr"; |
| 1159 | + $wl{120186}="/opt/staroffice8/share/config/javasettingsunopkginstall.xml"; |
| 1160 | + $wl{120223}="/kernel/drv/emlxs.conf"; |
| 1161 | + $wl{120273}="/etc/sma/snmp/snmpd.conf"; |
| 1162 | + $wl{120347}="/etc/hba.conf"; |
| 1163 | + $wl{120411}="/etc/gtk-2.0/gtk.immodules /etc/amd64/gtk-2.0/gtk.immodules"; |
| 1164 | + $wl{120461}="/etc/gtk-2.0/gtk.immodules /etc/amd64/gtk-2.0/gtk.immodules"; |
| 1165 | + $wl{121431}="/etc/default/lu"; |
| 1166 | + $wl{122213}="/etc/gconf/gconf.xml.defaults/apps/panel/default_setup/general/%gconf.xml"; |
| 1167 | + $wl{124394}="/etc/security/auth_attr /etc/security/prof_attr"; |
| 1168 | + $wl{125165}="/kernel/drv/qlc.conf"; |
| 1169 | + $wl{125216}="/etc/wgetrc"; |
| 1170 | + $wl{127128}="/etc/krb5/krb5.conf /etc/logadm.conf /etc/pam.conf /etc/security/audit_warn /etc/security/auth_attr /etc/security/prof_attr /etc/shadow /etc/user_attr /kernel/drv/mpt.conf"; |
| 1171 | + $wl{127756}="/etc/logadm.conf"; |
| 1172 | + $wl{128307}="/etc/security/device_policy"; |
| 1173 | + $wl{137094}="/etc/logindevperm"; |
| 1174 | + $wl{137112}="/lib/libc.so.1"; |
| 1175 | + $wl{137275}="/etc/mnttab"; |
| 1176 | + |
| 1177 | + (-f $readme) || return (1); |
| 1178 | + open (README, "<$readme") || err ("Can't open $readme ($!)"); |
| 1179 | + |
| 1180 | + FILE: while (<README>) { |
| 1181 | + next if ($_ !~ /Files included with this patch:/); |
| 1182 | + LINE: while (<README>) { |
| 1183 | + chomp; |
| 1184 | + next if (/^$/); |
| 1185 | + last FILE if (! /\//); |
| 1186 | + next if (/ELF/); # Ignore files with "ELF" in pathname - pkgchk bug |
| 1187 | + s/\s+\(deleted\)//; |
| 1188 | + s/\s+\<deleted\>//; |
| 1189 | + s/\(deleted\)$//; |
| 1190 | + s/\(deleted file\)$//; |
| 1191 | + s/^\s+//; |
| 1192 | + s/^/\// unless /^\//; |
| 1193 | + |
| 1194 | + foreach my $i (split (/ /, $wl{all})) { ($_ eq $i) && next LINE; } |
| 1195 | + if ($wl{$id}) { |
| 1196 | + foreach my $i (split (/ /, $wl{$id})) { ($_ eq $i) && next LINE; } |
| 1197 | + } |
| 1198 | + push (@files, $_); |
| 1199 | + } |
| 1200 | + } |
| 1201 | + close (README); |
| 1202 | + dbg ("Number of files to check: ", $#files+1); |
| 1203 | + ($#files == -1) && return (1); |
| 1204 | + |
| 1205 | + # pkgchk has a limit of 1024 pathnames |
| 1206 | + my @tfiles=@files; my $out=''; |
| 1207 | + while ($#tfiles != -1) { |
| 1208 | + my $fc=$#tfiles; |
| 1209 | + ($fc >= 1023) && ($fc=1023); |
| 1210 | + my $pfile="$o{tmpdir}/pca.pkgchk." . time() . $$; |
| 1211 | + open (PFILE, ">$pfile") || err ("Can't open $pfile ($!)"); |
| 1212 | + foreach my $f (@tfiles[0..$fc]) { print PFILE "$f\n" } |
| 1213 | + close PFILE; |
| 1214 | + $out .= `$pkgchk $o{root} -q -i $pfile 2>&1`; |
| 1215 | + unlink $pfile; |
| 1216 | + for (0..1023) { shift @tfiles; } |
| 1217 | + } |
| 1218 | + ($out) || return (1); |
| 1219 | + |
| 1220 | + if ($out =~ /file size |file cksum |pathname |pkgchk: ERROR/) { |
| 1221 | + print "failed file verification:\n\n$out"; |
| 1222 | + return (0); |
| 1223 | + } |
| 1224 | + return (1); |
| 1225 | +} |
| 1226 | + |
| 1227 | +sub patch_apply_check { |
| 1228 | + my $id=$_[0]; |
| 1229 | + |
| 1230 | + if ($id =~ /113039|113040|113041|113042|113043/) { |
| 1231 | + if (!$pkgs{"SUNWsan"}) { return (0) } |
| 1232 | + } |
| 1233 | + |
| 1234 | + if ($id eq "114045") { |
| 1235 | + if ((exists $p{114049}) && ($p{114049}{irev} gt '03')) { return (0) } |
| 1236 | + } |
| 1237 | + |
| 1238 | + if (($id =~ /114046|119209/) && ($u{osrel} ne "5.8")) { return (0) } |
| 1239 | + if (($id =~ /114049|114050/) && ($u{osrel} ne "5.9")) { return (0) } |
| 1240 | + if (($id =~ /119211|119212/) && ($u{osrel} ne "5.9")) { return (0) } |
| 1241 | + |
| 1242 | + if ($id eq "114790") { |
| 1243 | + if (!$pkgs{"SUNWdcar"} || $pkgs{"SUNWdcar"} !~ "<1.1.0,REV=2002.05.29.15.02>") { return (0) } |
| 1244 | + if (!$pkgs{"SUNWcrypr"} || $pkgs{"SUNWcrypr"} !~ "<1.1.0,REV=2002.05.29.15.00>") { return (0) } |
| 1245 | + } |
| 1246 | + |
| 1247 | + if (($id =~ /117765|117766/) && ($u{osrel} ne "5.8")) { return (0) } |
| 1248 | + if (($id =~ /117767|117768/) && ($u{osrel} ne "5.9")) { return (0) } |
| 1249 | + |
| 1250 | + if ($id eq "113332") { |
| 1251 | + if (($pkgs{"SUNWhea"}) || ($pkgs{"SUNWmdb"})) { return (1) } |
| 1252 | + if (($u{model} eq 'sun4u') || ($u{model} eq 'sun4us')) { return (1) } |
| 1253 | + return (0); |
| 1254 | + } |
| 1255 | + |
| 1256 | + if ($id =~ /115010|116478/) { |
| 1257 | + if (($pkgs{"SUNWhea"}) || ($pkgs{"SUNWmdb"})) { return (1) } |
| 1258 | + if ($u{model} eq 'sun4u') { return (1) } |
| 1259 | + return (0); |
| 1260 | + } |
| 1261 | + |
| 1262 | + if ($id =~ /109077|109078/) { |
| 1263 | + if ((!$pkgs{"SUNWdhcm"}) && (!$pkgs{"SUNWdhcsu"})) { return (0) } |
| 1264 | + if ($pkgs{"SUNWj3rt"}) { return (1) } |
| 1265 | + return (0); |
| 1266 | + } |
| 1267 | + |
| 1268 | + if ($id =~ /118739|116706/) { |
| 1269 | + if (!$pkgs{"SUNWtsr"} || $pkgs{"SUNWtsr"} !~ "<2.5.0,REV=2003.04.03.21.27>") { return (0) } |
| 1270 | + } |
| 1271 | + if ($id =~ /118740|116707/) { |
| 1272 | + if (!$pkgs{"SUNWtsr"} || $pkgs{"SUNWtsr"} !~ "<2.5.0,REV=2003.04.03.19.26>") { return (0) } |
| 1273 | + } |
| 1274 | + if ($id eq "118741") { |
| 1275 | + if (!$pkgs{"SUNWtsr"} || $pkgs{"SUNWtsr"} !~ "<2.5.0,REV=2003.11.11.23.55>") { return (0) } |
| 1276 | + } |
| 1277 | + if ($id eq "118742") { |
| 1278 | + if (!$pkgs{"SUNWtsr"} || $pkgs{"SUNWtsr"} !~ "<2.5.0,REV=2003.11.11.20.36>") { return (0) } |
| 1279 | + } |
| 1280 | + |
| 1281 | + if ($id eq "110692") { |
| 1282 | + if ((exists $p{108806}) && ($p{108806}{irev} ge '01')) { return (0) } |
| 1283 | + if ((exists $p{108806}) && ($p{108806}{crev} ge '01')) { return (0) } |
| 1284 | + } |
| 1285 | + |
| 1286 | + if ($id eq "111412") { |
| 1287 | + if (!$pkgs{"SUNWmdi"} || $pkgs{"SUNWmdi"} !~ "<11.8.0,REV=2001.01.19.01.02>") { return (0) } |
| 1288 | + if (!$pkgs{"SUNWsan"}) { return (0) } |
| 1289 | + } |
| 1290 | + if ($id =~ /111095|111096|111413/) { |
| 1291 | + if (!$pkgs{"SUNWsan"}) { return (0) } |
| 1292 | + } |
| 1293 | + if ($id eq "111097") { |
| 1294 | + if (!$pkgs{"SUNWsan"}) { return (0) } |
| 1295 | + if (!$pkgs{"SUNWqlc"}) { return (0) } |
| 1296 | + } |
| 1297 | + |
| 1298 | + if ($id eq "111656") { |
| 1299 | + if (!((exists $p{109460}) && ($p{109460}{irev} eq '05'))) { return (0) } |
| 1300 | + } |
| 1301 | + if ($id eq "111658") { |
| 1302 | + if (!((exists $p{107469}) && ($p{107469}{irev} eq '08'))) { return (0) } |
| 1303 | + } |
| 1304 | + if ($id eq "111079") { |
| 1305 | + if (!((exists $p{105375}) && ($p{105375}{irev} eq '26'))) { return (0) } |
| 1306 | + } |
| 1307 | + |
| 1308 | + if ($id eq "107474") { |
| 1309 | + if ((exists $p{107292}) && ($p{107292}{irev} ge '02')) { return (1) } |
| 1310 | + return (0); |
| 1311 | + } |
| 1312 | + |
| 1313 | + if ($id eq "106533") { |
| 1314 | + if ($u{platform} ne 'SUNW,UltraSPARC-IIi-cEngine') { return (0) } |
| 1315 | + } |
| 1316 | + if ($id eq "106629") { |
| 1317 | + if ($u{platform} ne 'CYRS,Superserver-6400') { return (0) } |
| 1318 | + } |
| 1319 | + if ($id eq "112780") { |
| 1320 | + if (!($u{model} eq 'sun4u')) { return (0) } |
| 1321 | + } |
| 1322 | + if ($id eq "112327") { |
| 1323 | + if (($u{osrel} ne "5.6") && ($u{osrel} ne "5.7")) { return (0) } |
| 1324 | + } |
| 1325 | + |
| 1326 | + if ($id =~ /11464[456789]|11465[0123]|11481[67]|11578[01]|11752[01]/) { |
| 1327 | + if ($u{osrel} ne "5.8") { return (0) } |
| 1328 | + } |
| 1329 | + if ($id =~ /11468[6789]|11469[012345]|11481[89]|11578[23]|11752[67]/) { |
| 1330 | + if ($u{osrel} ne "5.9") { return (0) } |
| 1331 | + } |
| 1332 | + |
| 1333 | + if ($id eq "111891") { |
| 1334 | + if (!$pkgs{"SUNWutr"} || $pkgs{"SUNWutr"} !~ "<1.3_12.c,REV=2001.07.16.20.52>") { return (0) } |
| 1335 | + } |
| 1336 | + |
| 1337 | + if (($id eq "114255") && ($u{arch} ne "sparc")) { return (0) } |
| 1338 | + if (($id eq "114256") && ($u{arch} ne "i386")) { return (0) } |
| 1339 | + |
| 1340 | + if (($id eq "115328") && ($u{osrel} ne "5.8")) { return (0) } |
| 1341 | + if (($id eq "115342") && ($u{osrel} ne "5.9")) { return (0) } |
| 1342 | + if (($id eq "115343") && ($u{osrel} ne "5.9")) { return (0) } |
| 1343 | + if (($id eq "119346") && ($u{osrel} ne "5.10")) { return (0) } |
| 1344 | + |
| 1345 | + if (($id eq "115766") && ($u{arch} ne "sparc")) { return (0) } |
| 1346 | + if (($id eq "120091") && ($u{arch} ne "i386")) { return (0) } |
| 1347 | + if (($id eq "120879") && ($u{arch} ne "sparc")) { return (0) } |
| 1348 | + if (($id eq "120880") && ($u{arch} ne "i386")) { return (0) } |
| 1349 | + if (($id eq "120954") && ($u{arch} ne "sparc")) { return (0) } |
| 1350 | + if (($id eq "120955") && ($u{arch} ne "i386")) { return (0) } |
| 1351 | + |
| 1352 | + if (($id =~ /115835|115836/) && (!$pkgs{"SUNWgscr"})) { return (0) } |
| 1353 | + |
| 1354 | + if (($id eq "119300") && ($u{osrel} ne "5.8")) { return (0) } |
| 1355 | + if (($id eq "119301") && ($u{osrel} ne "5.9")) { return (0) } |
| 1356 | + if (($id eq "119302") && ($u{osrel} ne "5.10")) { return (0) } |
| 1357 | + |
| 1358 | + if ($id =~ /109357/) { |
| 1359 | + if ((exists $p{109778}) && ($p{109778}{irev} ge '08')) { return (0) } |
| 1360 | + if ((exists $p{109778}) && ($p{109778}{crev} ge '08')) { return (0) } |
| 1361 | + } |
| 1362 | + if (($id eq "113434") && (!$pkgs{"SUNWwbsup"})) { return (0) } |
| 1363 | + |
| 1364 | + if (($id eq "109700") && ($u{osrel} ne "5.6")) { return (0) } |
| 1365 | + if (($id eq "109701") && ($u{osrel} ne "5.7")) { return (0) } |
| 1366 | + if (($id eq "111248") && ($u{osrel} ne "5.6")) { return (0) } |
| 1367 | + if (($id eq "111249") && ($u{osrel} ne "5.7")) { return (0) } |
| 1368 | + if (($id eq "111250") && ($u{osrel} ne "5.8")) { return (0) } |
| 1369 | + if (($id eq "115548") && ($u{osrel} ne "5.9")) { return (0) } |
| 1370 | + |
| 1371 | + if (($id eq "108553") && ($u{osrel} ne "5.8")) { return (0) } |
| 1372 | + if (($id eq "108834") && (($u{osrel} ne "5.5.1") || ($u{osrel} ne "5.6") || ($u{osrel} ne "5.7"))) { return (0) } |
| 1373 | + if (($id eq "112125") && (($u{osrel} ne "5.6") || ($u{osrel} ne "5.7"))) { return (0) } |
| 1374 | + if (($id eq "112126") && (($u{osrel} ne "5.8") || ($u{osrel} ne "5.9"))) { return (0) } |
| 1375 | + |
| 1376 | + if (($id eq "123200") && ($u{osrel} ne "5.8")) { return (0) } |
| 1377 | + if (($id eq "123201") && ($u{osrel} ne "5.9")) { return (0) } |
| 1378 | + if (($id eq "123202") && ($u{osrel} ne "5.10")) { return (0) } |
| 1379 | + |
| 1380 | + if (($id eq "119527") && ($u{arch} ne "sparc")) { return (0) } |
| 1381 | + if (($id eq "119528") && ($u{arch} ne "i386")) { return (0) } |
| 1382 | + if (($id eq "119530") && ($u{arch} ne "sparc")) { return (0) } |
| 1383 | + if (($id eq "119531") && ($u{arch} ne "i386")) { return (0) } |
| 1384 | + if (($id eq "119325") && ($u{arch} ne "sparc")) { return (0) } |
| 1385 | + if (($id eq "119326") && ($u{arch} ne "i386")) { return (0) } |
| 1386 | + |
| 1387 | + if (($id eq "127498") && ($u{osrel} ne "5.8")) { return (0) } |
| 1388 | + if (($id eq "127499") && ($u{osrel} ne "5.8")) { return (0) } |
| 1389 | + |
| 1390 | + if (($id eq "136986") && ($u{osrel} ne "5.8")) { return (0) } |
| 1391 | + if (($id eq "136987") && ($u{osrel} ne "5.8")) { return (0) } |
| 1392 | + if (($id eq "125950") && ($u{osrel} ne "5.9")) { return (0) } |
| 1393 | + if (($id eq "125951") && ($u{osrel} ne "5.9")) { return (0) } |
| 1394 | + if (($id eq "125952") && ($u{osrel} ne "5.10")) { return (0) } |
| 1395 | + if (($id eq "125953") && ($u{osrel} ne "5.10")) { return (0) } |
| 1396 | + |
| 1397 | + if (($id eq "121430") && ($p{121430}{crev} ge '16') && (!$pkgs{"SUNWlucfg"})) { return (0) } |
| 1398 | + if (($id eq "121431") && ($p{121431}{crev} ge '17') && (!$pkgs{"SUNWlucfg"})) { return (0) } |
| 1399 | + if (($id eq "121428") && ($p{121428}{crev} ge '08')) { |
| 1400 | + if (!((exists $p{121430}) && ($p{121430}{irev} ge '16'))) { return (0) } |
| 1401 | + } |
| 1402 | + if (($id eq "121429") && ($p{121429}{crev} ge '08')) { |
| 1403 | + if (!((exists $p{121431}) && ($p{121431}{irev} ge '16'))) { return (0) } |
| 1404 | + } |
| 1405 | + |
| 1406 | + if (($id eq "125276") && ($u{arch} ne "sparc")) { return (0) } |
| 1407 | + if (($id eq "125277") && (($u{osrel} ne "5.9") || ($u{arch} ne "i386"))) { return (0) } |
| 1408 | + if (($id eq "125278") && (($u{osrel} ne "5.10") || ($u{arch} ne "i386"))) { return (0) } |
| 1409 | + |
| 1410 | + if (($id eq "123827") && ($u{osrel} ne "5.8")) { return (0) } |
| 1411 | + if (($id eq "123828") && ($u{osrel} ne "5.9")) { return (0) } |
| 1412 | + if (($id eq "123829") && ($u{osrel} ne "5.10")) { return (0) } |
| 1413 | + |
| 1414 | + if (($id eq "125760") && ($u{osrel} ne "5.8")) { return (0) } |
| 1415 | + if (($id eq "125761") && ($u{osrel} ne "5.9")) { return (0) } |
| 1416 | + if (($id eq "125762") && ($u{osrel} ne "5.10")) { return (0) } |
| 1417 | + |
| 1418 | + if ($id =~ /120971|120972|120973|122803|122804|122805|126507|126508|126506/) { |
| 1419 | + if (!($pkgs{"SUNWsamfsr"} || $pkgs{"SUNWsamfsu"})) { return (0) } |
| 1420 | + } |
| 1421 | + if ($id =~ /120974|120975|120976|122806|122807|122808|126511|126512|126510/) { |
| 1422 | + if (!($pkgs{"SUNWqfsr"} || $pkgs{"SUNWqfsu"})) { return (0) } |
| 1423 | + } |
| 1424 | + |
| 1425 | + if (($id eq "106514") && ($u{arch} ne "sparc")) { return (0) } |
| 1426 | + if (($id eq "106515") && ($u{arch} ne "i386")) { return (0) } |
| 1427 | + if (($id eq "108049") && ($u{arch} ne "sparc")) { return (0) } |
| 1428 | + if (($id eq "108050") && ($u{arch} ne "i386")) { return (0) } |
| 1429 | + if (($id eq "108879") && ($u{arch} ne "sparc")) { return (0) } |
| 1430 | + if (($id eq "108881") && ($u{arch} ne "i386")) { return (0) } |
| 1431 | + if (($id eq "109120") && ($u{arch} ne "sparc")) { return (0) } |
| 1432 | + if (($id eq "109121") && ($u{arch} ne "i386")) { return (0) } |
| 1433 | + if (($id eq "109413") && ($u{arch} ne "sparc")) { return (0) } |
| 1434 | + if (($id eq "109414") && ($u{arch} ne "i386")) { return (0) } |
| 1435 | + if (($id eq "117784") && ($u{arch} ne "sparc")) { return (0) } |
| 1436 | + if (($id eq "117785") && ($u{arch} ne "i386")) { return (0) } |
| 1437 | + if (($id eq "118195") && ($u{arch} ne "sparc")) { return (0) } |
| 1438 | + if (($id eq "118196") && ($u{arch} ne "i386")) { return (0) } |
| 1439 | + if (($id eq "118263") && ($u{arch} ne "sparc")) { return (0) } |
| 1440 | + if (($id eq "118264") && ($u{arch} ne "i386")) { return (0) } |
| 1441 | + if (($id eq "118950") && ($u{arch} ne "sparc")) { return (0) } |
| 1442 | + if (($id eq "118951") && ($u{arch} ne "i386")) { return (0) } |
| 1443 | + if (($id eq "123254") && ($u{arch} ne "sparc")) { return (0) } |
| 1444 | + if (($id eq "124590") && ($u{arch} ne "i386")) { return (0) } |
| 1445 | + |
| 1446 | + if (($id eq "124480") && (($u{osrel} ne "5.9") || ($u{arch} ne "sparc"))) { return (0) } |
| 1447 | + if (($id eq "124481") && (($u{osrel} ne "5.10") || ($u{arch} ne "sparc"))) { return (0) } |
| 1448 | + if (($id eq "124482") && (($u{osrel} ne "5.10") || ($u{arch} ne "i386"))) { return (0) } |
| 1449 | + |
| 1450 | + if (($id eq "126356") && ($u{arch} ne "sparc")) { return (0) } |
| 1451 | + if (($id eq "126357") && ($u{arch} ne "i386")) { return (0) } |
| 1452 | + |
| 1453 | + if (($id eq "117429") && ($u{osrel} ne "5.9")) { return (0) } |
| 1454 | + if (($id eq "118386") && ($u{osrel} ne "5.6")) { return (0) } |
| 1455 | + if (($id eq "118387") && ($u{osrel} ne "5.7")) { return (0) } |
| 1456 | + if (($id eq "118388") && ($u{osrel} ne "5.8")) { return (0) } |
| 1457 | + if (($id eq "118389") && ($u{osrel} ne "5.9")) { return (0) } |
| 1458 | + if (($id eq "118828") && ($u{osrel} ne "5.8")) { return (0) } |
| 1459 | + if (($id eq "118829") && ($u{osrel} ne "5.9")) { return (0) } |
| 1460 | + if (($id eq "118836") && ($u{osrel} ne "5.6")) { return (0) } |
| 1461 | + if (($id eq "118837") && ($u{osrel} ne "5.7")) { return (0) } |
| 1462 | + if (($id eq "118838") && ($u{osrel} ne "5.8")) { return (0) } |
| 1463 | + if (($id eq "118839") && ($u{osrel} ne "5.9")) { return (0) } |
| 1464 | + if (($id eq "118840") && ($u{osrel} ne "5.9")) { return (0) } |
| 1465 | + if (($id eq "120376") && ($u{osrel} ne "5.6")) { return (0) } |
| 1466 | + if (($id eq "120377") && ($u{osrel} ne "5.7")) { return (0) } |
| 1467 | + if (($id eq "120378") && ($u{osrel} ne "5.8")) { return (0) } |
| 1468 | + if (($id eq "120379") && ($u{osrel} ne "5.9")) { return (0) } |
| 1469 | + if (($id eq "124689") && ($u{osrel} ne "5.8")) { return (0) } |
| 1470 | + if (($id eq "124690") && ($u{osrel} ne "5.9")) { return (0) } |
| 1471 | + |
| 1472 | + if (($id eq "116338") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1473 | + if (($id eq "116339") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1474 | + if (($id eq "118383") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1475 | + if (($id eq "118384") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1476 | + if (($id eq "125698") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1477 | + if (($id eq "125699") && (!$pkgs{"SUNWxwplt"} || $pkgs{"SUNWxwplt"} !~ "<3.8.1800,REV=0.99.03.23>")) { return (0) } |
| 1478 | + |
| 1479 | + if (($id eq "111857") && ($u{osrel} ne "5.8")) { return (0) } |
| 1480 | + if (($id eq "114176") && ($u{osrel} ne "5.9")) { return (0) } |
| 1481 | + |
| 1482 | + if (($id eq "119380") && ($u{osrel} ne "5.8")) { return (0) } |
| 1483 | + if (($id eq "119381") && ($u{osrel} ne "5.9") && ($u{osrel} ne "5.10")) { return (0) } |
| 1484 | + |
| 1485 | + if (($id eq "125445") && ($u{osrel} ne "5.9")) { return (0) } |
| 1486 | + if (($id eq "125446") && ($u{osrel} ne "5.10")) { return (0) } |
| 1487 | + |
| 1488 | + if (($id eq "127553") && ($u{arch} ne "sparc")) { return (0) } |
| 1489 | + if (($id eq "127554") && ($u{arch} ne "i386")) { return (0) } |
| 1490 | + |
| 1491 | + if (($id eq "121708") && ($u{osrel} ne "5.8")) { return (0) } |
| 1492 | + if (($id eq "121709") && ($u{osrel} ne "5.9")) { return (0) } |
| 1493 | + if (($id eq "121710") && ($u{osrel} ne "5.10")) { return (0) } |
| 1494 | + |
| 1495 | + if (($id eq "125848") && ($u{osrel} ne "5.8")) { return (0) } |
| 1496 | + if (($id eq "125849") && ($u{osrel} ne "5.9")) { return (0) } |
| 1497 | + if (($id eq "125850") && ($u{osrel} ne "5.10")) { return (0) } |
| 1498 | + |
| 1499 | + return (1); |
| 1500 | +} |
| 1501 | + |
| 1502 | +sub get_uname { |
| 1503 | + # Get information about host |
| 1504 | + open(UNAME, $input{uname}) || err ("Can't open $input{uname} ($!)"); |
| 1505 | + $_=<UNAME>; |
| 1506 | + $_ || err ("Empty uname output"); |
| 1507 | + chomp; |
| 1508 | + close UNAME; |
| 1509 | + |
| 1510 | + ($u{osname}, $u{hostname}, $u{osrel}, $u{osversion}, $u{model}, $u{arch}, $u{platform})= split (/ /, $_); |
| 1511 | + ($u{osname} && $u{hostname} && $u{osrel} && $u{osversion} && $u{model} && $u{arch} && $u{platform}) || err ("Can't parse ouput from $input{uname}:\n $_"); |
| 1512 | +} |
| 1513 | + |
| 1514 | +sub get_installed_packages { |
| 1515 | + my $package; |
| 1516 | + |
| 1517 | + # Read pkginfo |
| 1518 | + open(PKGINFO, $input{pkginfo}) || err ("Can't open $input{pkginfo} ($!)"); |
| 1519 | + if ($input{pkginfo} =~ /pkginfo-l.out/) { |
| 1520 | + while(<PKGINFO>) { |
| 1521 | + if (/\s+PKGINST:\s+(\S+)$/) { $package = $1; } |
| 1522 | + if (/\s+VERSION:\s+(\S+)$/) { $pkgs{$package} .= "<$1>"; } |
| 1523 | + } |
| 1524 | + } else { |
| 1525 | + while(<PKGINFO>) { |
| 1526 | + ($_ =~ /^(\S+) /) || err ("Can't parse output from $input{pkginfo}:\n $_"); |
| 1527 | + $package=$1; |
| 1528 | + # Removing trailing .2/.3/... (multiple versions of same package) |
| 1529 | + $package =~ s/\..*//; |
| 1530 | + $_= <PKGINFO>; |
| 1531 | + ($_ =~ / (\S+)$/) || err ("Can't parse output from $input{pkginfo}:\n $_"); |
| 1532 | + $pkgs{$package} .= "<$1>"; |
| 1533 | + } |
| 1534 | + } |
| 1535 | + close(PKGINFO); |
| 1536 | +} |
| 1537 | + |
| 1538 | +sub get_installed_patches { |
| 1539 | + my $list=''; |
| 1540 | + my $done=0; |
| 1541 | + |
| 1542 | + my $showrev_cmd=$showrev; ( -x $showrev_cmd) || ($showrev_cmd=''); |
| 1543 | + my $patchadd_cmd=$o{patchadd}; ( -x $patchadd_cmd) || ($patchadd_cmd=''); |
| 1544 | + |
| 1545 | + # On Solaris <= 8, showrev doesn't support -R. Use patchadd instead. |
| 1546 | + my ($major, $minor) = split (/\./, $u{osrel}); |
| 1547 | + if (($minor <= 8) && $o{root}) { $showrev_cmd='' } |
| 1548 | + |
| 1549 | + if ($o{fromfiles}) { |
| 1550 | + dbg ("Reading from $input{showrev}"); |
| 1551 | + open(SHOWREV, $input{showrev}) || err ("Can't open $input{showrev} ($!)"); |
| 1552 | + $/=""; $list= <SHOWREV>; $/="\n"; |
| 1553 | + close SHOWREV; |
| 1554 | + $done=1; |
| 1555 | + } else { |
| 1556 | + foreach my $cmd ($showrev_cmd, $patchadd_cmd) { |
| 1557 | + next unless $cmd; |
| 1558 | + $input{showrev}="$cmd -p $o{root} 2>/dev/null"; |
| 1559 | + dbg ("Reading from $input{showrev}"); |
| 1560 | + $list=`$input{showrev}`; |
| 1561 | + if (!$?) { $done=1; last } else { dbg ("Failed: $list") } |
| 1562 | + } |
| 1563 | + } |
| 1564 | + $done || err ("Couldn't get list of installed patches"); |
| 1565 | + |
| 1566 | + $list || ($list= "No patches are installed\n"); |
| 1567 | + my @list= split(/\n/, $list); |
| 1568 | + |
| 1569 | + foreach my $i (sort @list) { |
| 1570 | + # Known formats of patch IDs: |
| 1571 | + # 123456-78 : Regular Sun |
| 1572 | + # IDR123456-78 : Unsupported (pre-release) Sun |
| 1573 | + # 123-45 : EMC |
| 1574 | + # CKPSP123456-78 : Checkpoint |
| 1575 | + # CPFWSP410002-01: Checkpoint |
| 1576 | + # KDE20060107-01 : KDE |
| 1577 | + # IDCE32-02 : DCE |
| 1578 | + # DP550001-05 : HP Data Protector |
| 1579 | + # DP550011-1 : HP Data Protector |
| 1580 | + # PSE400SOL023 : Citrix |
| 1581 | + # ME113SB222 : Citrix |
| 1582 | + # Q995801-01 : SUNWluxop |
| 1583 | + # T000000-01 : Terix DST patch |
| 1584 | + if ( |
| 1585 | + ($i =~ /^Patch:\s+(\d{3,6})-(\d{2}).*/) || |
| 1586 | + ($i =~ /^Patch:\s+IDR(\d{6})-(\d{2}).*/) || |
| 1587 | + ($i =~ /^Patch:\s+CKPSP(\d{6})-(\d{2}).*/) || |
| 1588 | + ($i =~ /^Patch:\s+CPFWSP(\d{6})-(\d{2}).*/) || |
| 1589 | + ($i =~ /^Patch:\s+KDE(\d{8})-(\d{2}).*/) || |
| 1590 | + ($i =~ /^Patch:\s+IDCE(\d{2})-(\d{2}).*/) || |
| 1591 | + ($i =~ /^Patch:\s+DP(\d{6})-(\d{2}).*/) || |
| 1592 | + ($i =~ /^Patch:\s+DP(\d{6})-(\d{1}).*/) || |
| 1593 | + ($i =~ /^Patch:\s+PSE(\d{3})SOL(\d{3}).*/) || |
| 1594 | + ($i =~ /^Patch:\s+ME(\d{3})SB(\d{3}).*/) || |
| 1595 | + ($i =~ /^Patch:\s+Q(\d{6})-(\d{2}).*/) || |
| 1596 | + ($i =~ /^Patch:\s+T(\d{6})-(\d{2}).*/) |
| 1597 | + ) { |
| 1598 | + my ($id, $rev)=($1,$2); |
| 1599 | + init_patch($id); |
| 1600 | + $p{$id}{irev}= $rev; |
| 1601 | + if ($i =~ / Obsoletes: ([-0-9, ]*) /) { |
| 1602 | + for my $j (split (/,* /, $1)) { |
| 1603 | + my ($oid, $orev) = split (/-/, $j); |
| 1604 | + ($id eq $oid) && next; |
| 1605 | + init_patch($oid); |
| 1606 | + $p{$oid}{iobsoletedby}="$id-$rev"; |
| 1607 | + #dbg ("$oid-$orev obsoleted by $id-$rev"); |
| 1608 | + } |
| 1609 | + } |
| 1610 | + if ($i =~ / Incompatibles: ([-0-9, ]*) /) { |
| 1611 | + for my $j (split (/,* /, $1)) { |
| 1612 | + my ($iid, $irev) = split (/-/, $j); |
| 1613 | + init_patch($iid); |
| 1614 | + #dbg ("$iid-$irev incompatible with $id-$rev"); |
| 1615 | + } |
| 1616 | + } |
| 1617 | + next; |
| 1618 | + } |
| 1619 | + next if ($i =~ "No patches are installed"); |
| 1620 | + next if ($i =~ "No patches installed"); |
| 1621 | + next if ($i =~ /^$/); |
| 1622 | + print ("WARNING: Can't parse output from $input{showrev}:\n $i\n"); |
| 1623 | + } |
| 1624 | +} |
| 1625 | + |
| 1626 | +sub get_current_xref { |
| 1627 | + # Download most recent patchdiag.xref, if requested |
| 1628 | + |
| 1629 | + return if ($o{nocheckxref}); |
| 1630 | + |
| 1631 | + lock_free($o{xrefdir}, "xref", 60) || err ("Another instance of pca is downloading $input{xref} right now"); |
| 1632 | + |
| 1633 | + # Remove possibly left-over size zero file |
| 1634 | + if (-z $input{xref}) { unlink ($input{xref}) } |
| 1635 | + |
| 1636 | + # Check for existing and up to date local copy of xref file |
| 1637 | + if ((-f $input{xref}) && (!$o{getxref})) { |
| 1638 | + my $interval=10800; # 3 hours |
| 1639 | + my $current=(stat($input{xref}))[9]; |
| 1640 | + my $now=time(); |
| 1641 | + my $age=$now-$current; |
| 1642 | + dbg ("xref now : " . localtime($now)); |
| 1643 | + dbg ("xref current: " . localtime($current)); |
| 1644 | + dbg ("xref age : " . $age); |
| 1645 | + if ($age < $interval) { |
| 1646 | + dbg ("Local file $input{xref} is up to date"); |
| 1647 | + return; |
| 1648 | + } |
| 1649 | + } |
| 1650 | + out ('info', "Downloading xref file to $input{xref}"); |
| 1651 | + |
| 1652 | + # Check if we can write to xref directory |
| 1653 | + if (! -w $o{xrefdir}) { |
| 1654 | + my $msg="Can't write to xref download directory $o{xrefdir}"; |
| 1655 | + if ($o{getxref} || (! -f $input{xref})) { |
| 1656 | + err ($msg) |
| 1657 | + } else { out ('info', $msg); return } |
| 1658 | + } |
| 1659 | + # Check if we can write to xref file |
| 1660 | + if ((-f $input{xref}) && (! -w $input{xref})) { |
| 1661 | + my $msg="Can't write to $input{xref}"; |
| 1662 | + if ($o{getxref}) { |
| 1663 | + err ($msg) |
| 1664 | + } else { out ('info', $msg); return } |
| 1665 | + } |
| 1666 | + |
| 1667 | + lock_create($o{xrefdir}, "xref", 1) || err ("Another instance of pca is downloading $input{xref} right now"); |
| 1668 | + (-s $input{xref}) && rename ("$input{xref}", "$input{xref}.tmp"); |
| 1669 | + |
| 1670 | + if ($o{xrefurl} =~ /^file:/) { |
| 1671 | + out ('info', "Trying $o{xrefurl}"); |
| 1672 | + my $path=$o{xrefurl}; $path =~ s/^file://; |
| 1673 | + (-r "$path/patchdiag.xref") && copy ("$path/patchdiag.xref", $input{xref}); |
| 1674 | + if (-s $input{xref}) { goto DONE } else { out ('info', "Failed") } |
| 1675 | + } |
| 1676 | + # Without wget we can't download patchdiag.xref |
| 1677 | + if (!$o{wget}) { |
| 1678 | + out ('info', "Failed (can't find wget executable)"); goto FAIL; |
| 1679 | + } |
| 1680 | + if ($o{xrefurl} =~ /^http:|^https:|^ftp/) { |
| 1681 | + out ('info', "Trying $o{xrefurl}"); |
| 1682 | + if (download("xref", "", "local", $input{xref}, "")) { goto DONE } else { out ('info', "Failed") } |
| 1683 | + } |
| 1684 | + my $try=1; my $ret=0; |
| 1685 | + while ($try <= $o{dltries} ) { |
| 1686 | + out ('info', "Trying $o{ssprot}://$o{sshost}/patchdiag.xref ($try/$o{dltries})"); |
| 1687 | + $ret=download("xref", "", "sunsolve", $input{xref}, ""); |
| 1688 | + last if ($ret); |
| 1689 | + $try++; if ($try <= $o{dltries}) { sleep ($try*2) } |
| 1690 | + } |
| 1691 | + if ($ret) { goto DONE } else { out ('info', "Failed") } |
| 1692 | + |
| 1693 | +FAIL: |
| 1694 | + out ('info', "Failed (patchdiag.xref not found)"); |
| 1695 | +DONE: |
| 1696 | + # If we have a backup copy and the download failed, use the backup |
| 1697 | + if (-s "$input{xref}.tmp" && ! -s $input{xref}) { |
| 1698 | + rename ("$input{xref}.tmp", "$input{xref}") |
| 1699 | + } |
| 1700 | + # If we have a backup copy, check if the downloaded file is newer |
| 1701 | + if (-s "$input{xref}.tmp") { |
| 1702 | + my $odate; my $ndate; my $oage=-1; my $nage=-1; |
| 1703 | + open (XREF, "<$input{xref}.tmp"); |
| 1704 | + while (<XREF>) { |
| 1705 | + if ($_ =~ /PATCHDIAG TOOL CROSS-REFERENCE FILE AS OF (.*) /) { |
| 1706 | + $oage= calculateage ($odate=$1); dbg ("old xref age: $oage"); last; |
| 1707 | + } |
| 1708 | + } |
| 1709 | + close XREF; |
| 1710 | + open (XREF, "<$input{xref}"); |
| 1711 | + while (<XREF>) { |
| 1712 | + if ($_ =~ /PATCHDIAG TOOL CROSS-REFERENCE FILE AS OF (.*) /) { |
| 1713 | + $nage= calculateage ($ndate=$1); dbg ("new xref age: $nage"); last; |
| 1714 | + } |
| 1715 | + } |
| 1716 | + close XREF; |
| 1717 | + if ((($oage == -1) && ($nage != -1)) || (($oage != -1) && ($nage != -1) && ($nage <= $oage))) { |
| 1718 | + unlink ("$input{xref}.tmp") |
| 1719 | + } else { |
| 1720 | + out ('info', "Downloaded file ($ndate) older than local file ($odate)"); |
| 1721 | + rename ("$input{xref}.tmp", "$input{xref}") |
| 1722 | + } |
| 1723 | + } |
| 1724 | + lock_remove($o{xrefdir}, "xref"); |
| 1725 | + |
| 1726 | + if (-s $input{xref}) { |
| 1727 | + my $now=time(); utime $now, $now, $input{xref}; |
| 1728 | + if ($o{xrefown} || ($o{xrefdir} =~ /\/home\//)) { |
| 1729 | + chmod 0644, $input{xref}; |
| 1730 | + } else { |
| 1731 | + chmod 0666, $input{xref}; |
| 1732 | + } |
| 1733 | + return; |
| 1734 | + } |
| 1735 | + (-z $input{xref}) && unlink ($input{xref}); |
| 1736 | +} |
| 1737 | + |
| 1738 | +sub get_current_patches { |
| 1739 | + # Read patchdiag.xref |
| 1740 | + # |
| 1741 | + (-z $input{xref}) && err ("Empty file $input{xref}"); |
| 1742 | + open(XREF, "<$input{xref}") || err ("Can't open xref file $input{xref} ($!)"); |
| 1743 | + while (<XREF>) { |
| 1744 | + if ($_ =~ /PATCHDIAG TOOL CROSS-REFERENCE FILE AS OF (.*) /) { |
| 1745 | + out ('info', "Using $input{xref} from $1"); last; |
| 1746 | + } |
| 1747 | + } |
| 1748 | + $/=""; my $xref= <XREF>; $/="\n"; |
| 1749 | + close XREF; |
| 1750 | + |
| 1751 | + if (!$xref) { err ("Corrupt file $input{xref}") } |
| 1752 | + |
| 1753 | + my @xref= split( /\n/, $xref ); |
| 1754 | + |
| 1755 | + # Build our patch information table from the xref file. |
| 1756 | + # patchdiag.xref is sorted, so if multiple revisions of a patch are listed, |
| 1757 | + # the one with the highest revision comes last. |
| 1758 | + # |
| 1759 | + foreach my $i (sort @xref) { |
| 1760 | + # Ignore comment lines and HTML tags |
| 1761 | + next if (($i =~ /^##/) || ($i =~ /^</)); |
| 1762 | + if ($i !~ /^\d{6}\|\d{2}\|.*\|.\|.\|.\|..\|.*\|.*\|.*\|.*$/) { err ("Can't parse input from $input{xref}:\n $i") } |
| 1763 | + |
| 1764 | + my ($id, $crev, $reldate, $rFlag, $sFlag, $oFlag, $byFlag, $os, |
| 1765 | + $archs, $pkgs, $synopsis )= split( /\|/, $i); |
| 1766 | + |
| 1767 | + init_patch($id); |
| 1768 | + |
| 1769 | + # If an installed patch revision is marked bad, note this. |
| 1770 | + if (($p{$id}{irev} eq $crev) && ($byFlag =~ ".B")) { |
| 1771 | + $p{$id}{ibad}= 1; |
| 1772 | + dbg ("Bad patch installed: $id-$p{$id}{irev}"); |
| 1773 | + } |
| 1774 | + |
| 1775 | + # If a patch revision is obsoleted or bad, use either the highest |
| 1776 | + # non-obsoleted revision, or the highest obsoleted revision if all |
| 1777 | + # revisions are obsoleted or bad. |
| 1778 | + # |
| 1779 | + if ($p{$id}{crev} ne "00") { |
| 1780 | + if (($oFlag eq "O") || ($byFlag =~ ".B")) { |
| 1781 | + if (!$p{$id}{obs} && !$p{$id}{bad}) { next; } |
| 1782 | + } |
| 1783 | + } |
| 1784 | + |
| 1785 | + $p{$id}{crev}=$crev; |
| 1786 | + if ($reldate ne '') { $p{$id}{reldate}=$reldate; } |
| 1787 | + $p{$id}{rec}=0; if ($rFlag eq 'R' ) { $p{$id}{rec}=1; } |
| 1788 | + $p{$id}{sec}=0; if ($sFlag eq 'S' ) { $p{$id}{sec}=1; } |
| 1789 | + $p{$id}{obs}=0; if ($oFlag eq 'O' ) { $p{$id}{obs}=1; } |
| 1790 | + $p{$id}{bad}=0; if ($byFlag =~ ".B") { $p{$id}{bad}=1; } |
| 1791 | + $p{$id}{y2k}=0; if ($byFlag =~ "Y.") { $p{$id}{y2k}=1; } |
| 1792 | + $p{$id}{os}=$os; |
| 1793 | + $p{$id}{synopsis}=$synopsis; |
| 1794 | + |
| 1795 | + # If a patch is obsoleted by another patch, note it. |
| 1796 | + # There are (at least) two forms, one with a patch revision |
| 1797 | + # and one without. We check for both. |
| 1798 | + # |
| 1799 | + if ($p{$id}{obs}) { |
| 1800 | + if ($synopsis =~ /Obsoleted by[ :]*(\d{6})-(\d{2})/) { |
| 1801 | + if ($id ne $1) { |
| 1802 | + $p{$id}{obsoletedby}="$1-$2"; |
| 1803 | + #dbg ("$id-$crev obsoleted by $p{$id}{obsoletedby}"); |
| 1804 | + } |
| 1805 | + } |
| 1806 | + if ($synopsis =~ /OBSOLETED by (\d{6})/) { |
| 1807 | + if ($id ne $1) { |
| 1808 | + $p{$id}{obsoletedby}="$1-01"; |
| 1809 | + #dbg ("$id-$crev obsoleted by $p{$id}{obsoletedby}"); |
| 1810 | + } |
| 1811 | + } |
| 1812 | + } |
| 1813 | + |
| 1814 | + # Patches might be obsoleted by installed patches, which are not |
| 1815 | + # (yet) listed in patchdiag.xref. |
| 1816 | + # |
| 1817 | + if (($p{$id}{iobsoletedby}) && (!$p{$id}{obs})) { |
| 1818 | + $p{$id}{obs}=1; |
| 1819 | + $p{$id}{obsoletedby}=$p{$id}{iobsoletedby}; |
| 1820 | + } |
| 1821 | + |
| 1822 | + # Patch requires are coded into the archs field - separate them. |
| 1823 | + $p{$id}{archs}=''; |
| 1824 | + $p{$id}{requires}=''; |
| 1825 | + foreach my $r (split /\;/, $archs) { |
| 1826 | + if ($r =~ /^\d{6}-\d{2}/) { |
| 1827 | + $p{$id}{requires} .= "$r;"; |
| 1828 | + # We run init_patch here for required patches because they might |
| 1829 | + # be missing in the xref file, and would be uninitialized later. |
| 1830 | + my ($r_id, $r_rev)= split (/-/, $r); |
| 1831 | + init_patch($r_id); |
| 1832 | + } else { |
| 1833 | + $p{$id}{archs} .= "$r;"; |
| 1834 | + } |
| 1835 | + } |
| 1836 | + # Patch incompatibilities are coded into the pkgs field |
| 1837 | + $p{$id}{pkgs}=''; |
| 1838 | + foreach my $r (split /\;/, $pkgs) { |
| 1839 | + if ($r =~ /^\d{6}-\d{2}/) { |
| 1840 | + my ($r_id, $r_rev)= split (/-/, $r); |
| 1841 | + init_patch($r_id); |
| 1842 | + #dbg ("$r_id-$r_rev incompatible with $id-$crev"); |
| 1843 | + } else { |
| 1844 | + $p{$id}{pkgs} .= "$r;"; |
| 1845 | + } |
| 1846 | + } |
| 1847 | + } |
| 1848 | +} |
| 1849 | + |
| 1850 | +sub init_patch { |
| 1851 | + my $id=$_[0]; |
| 1852 | + |
| 1853 | + # Every patch should be initialized only once. |
| 1854 | + return if ($p{$id}{init}); |
| 1855 | + |
| 1856 | + if($o{threads}) { |
| 1857 | + $p{$id}=&share({}); |
| 1858 | + $p{$id}{output} = &share([]); |
| 1859 | + } |
| 1860 | + |
| 1861 | + $p{$id}{irev}= $p{$id}{crev}= $p{$id}{prev}= '00'; |
| 1862 | + $p{$id}{synopsis}= 'NOT FOUND IN CROSS REFERENCE FILE!'; |
| 1863 | + $p{$id}{rec}= $p{$id}{sec}= $p{$id}{obs}= $p{$id}{bad}= $p{$id}{y2k}= 0; |
| 1864 | + $p{$id}{recf}= $p{$id}{secf}= 0; |
| 1865 | + $p{$id}{os}= ''; |
| 1866 | + $p{$id}{pkgs}= ''; |
| 1867 | + $p{$id}{stop}= ''; |
| 1868 | + $p{$id}{ignore}= ''; |
| 1869 | + $p{$id}{nobackup}= ''; |
| 1870 | + $p{$id}{reldate}= 'Jan/01/71'; |
| 1871 | + $p{$id}{obsoletedby}= ''; |
| 1872 | + $p{$id}{iobsoletedby}= ''; |
| 1873 | + $p{$id}{archs}= ''; |
| 1874 | + $p{$id}{requires}= ''; |
| 1875 | + $p{$id}{listed}= 0; |
| 1876 | + $p{$id}{ibad}= 0; |
| 1877 | + $p{$id}{init}= 1; |
| 1878 | + $p{$id}{dfori}= 0; |
| 1879 | + $p{$id}{dloutput}= ''; |
| 1880 | + $p{$id}{dlfile}= ''; |
| 1881 | +} |
| 1882 | + |
| 1883 | +sub print_patch { |
| 1884 | + my $id=$_[0]; |
| 1885 | + my ($char, $h_char, $irev, $crev, $rec, $sec, $bad, $age, $synopsis); |
| 1886 | + |
| 1887 | + if ($p{$id}{irev} lt $p{$id}{crev}) { $char='<'; $h_char='<'; } |
| 1888 | + if ($p{$id}{irev} eq $p{$id}{crev}) { $char='='; $h_char='='; } |
| 1889 | + if ($p{$id}{irev} gt $p{$id}{crev}) { $char='>'; $h_char='>'; } |
| 1890 | + |
| 1891 | + $irev= $p{$id}{irev}; if ($irev eq "00") { $irev= '--' }; |
| 1892 | + $crev= $p{$id}{crev}; if ($crev eq "00") { $crev= '--' }; |
| 1893 | + |
| 1894 | + $rec='-'; if ($p{$id}{recf}) { $rec='r'; }; if ($p{$id}{rec}) { $rec='R'; } |
| 1895 | + $sec='-'; if ($p{$id}{secf}) { $sec='s'; }; if ($p{$id}{sec}) { $sec='S'; } |
| 1896 | + $bad='-'; |
| 1897 | + if (($p{$id}{irev} eq "00") && ($p{$id}{bad} )) { $bad='B' } |
| 1898 | + if (($p{$id}{irev} ne "00") && ($p{$id}{ibad})) { $bad='B' } |
| 1899 | + |
| 1900 | + $synopsis= $p{$id}{synopsis}; |
| 1901 | + |
| 1902 | + $age=calculateage($p{$id}{reldate}); |
| 1903 | + if ($age > 999) { $age=999; } |
| 1904 | + |
| 1905 | + if (!$o{listhtml}) { |
| 1906 | + my $out=$o{format}; |
| 1907 | + $id=sprintf ("%6d", $id); $out =~ s/%p/$id/; |
| 1908 | + $out =~ s/%i/$irev/; $out =~ s/%e/$char/; $out =~ s/%c/$crev/; |
| 1909 | + $out =~ s/%r/$rec/; $out =~ s/%s/$sec/; $out =~ s/%b/$bad/; |
| 1910 | + $age=sprintf ("%3d", $age); $out =~ s/%a/$age/; |
| 1911 | + $out =~ s/%y/$synopsis/; |
| 1912 | + my $n=sprintf ("%3d", $c{current}); $out =~ s/%n/$n/; |
| 1913 | + my $t=sprintf ("%3d", $c{total}); $out =~ s/%t/$t/; |
| 1914 | + print "$out\n"; |
| 1915 | + } else { |
| 1916 | + # The patch download link will only work for patches in zip format, |
| 1917 | + # there is no way to determine if it's in zip or tar.Z here. |
| 1918 | + # |
| 1919 | + $synopsis =~ s/\&/\&/; |
| 1920 | + printf "<tr>"; |
| 1921 | + if ($o{patchurl} =~ /pca-proxy\.cgi/) { |
| 1922 | + printf "<td><a href=\"$o{patchurl}$id-$crev.zip\">%6d</a>", $id; |
| 1923 | + } else { |
| 1924 | + printf "<td><a href=\"$o{ssprot}://$o{sshost}/pdownload.do?target=$id-$crev&method=h\">%6d</a>", $id; |
| 1925 | + } |
| 1926 | + printf "<td>%2s<td>%1s<td>%2s<td>%1s%1s%1s<td align=right>%3s", $irev, $h_char, $crev, $rec, $sec, $bad, $age; |
| 1927 | + if ($o{patchurl} =~ /pca-proxy\.cgi/) { |
| 1928 | + printf "<td><a href=\"$o{patchurl}README.$id-$crev\">%s</a></tr>\n", $synopsis; |
| 1929 | + } else { |
| 1930 | + printf "<td><a href=\"$o{ssprot}://$o{sshost}/search/document.do?assetkey=$id\">%s</a></tr>\n", $synopsis; |
| 1931 | + } |
| 1932 | + } |
| 1933 | +} |
| 1934 | + |
| 1935 | +sub print_header { |
| 1936 | + if (!$o{listhtml} && !$o{noheader} && !$o{readme}) { |
| 1937 | + print "Host: $u{hostname} ($u{osname} $u{osrel}/$u{osversion}/$u{arch}/$u{model})\n"; |
| 1938 | + if ($o{root}) { my $r=$o{root}; $r =~ s/-R //; print "Root: $r\n" } |
| 1939 | + print "List: @slist\n\n"; |
| 1940 | + (@plist) || return; |
| 1941 | + |
| 1942 | + my $hdr= my $sep=$o{format}; |
| 1943 | + $hdr =~ s/%p/Patch /; $hdr =~ s/%i/IR/; $hdr =~ s/%e/ /; |
| 1944 | + $hdr =~ s/%c/CR/; $hdr =~ s/%r/R/; $hdr =~ s/%s/S/; |
| 1945 | + $hdr =~ s/%b/B/; $hdr =~ s/%a/Age/; $hdr =~ s/%y/Synopsis/; |
| 1946 | + $hdr =~ s/%n/Cnt/; $hdr =~ s/%t/Tot/; |
| 1947 | + $sep =~ s/%p/------/; $sep =~ s/%i/--/; $sep =~ s/%e/-/; $sep =~ s/%c/--/; |
| 1948 | + $sep =~ s/%r/-/; $sep =~ s/%s/-/; $sep =~ s/%b/-/; $sep =~ s/%a/---/; |
| 1949 | + $sep =~ s/%n/---/; $sep =~ s/%t/---/; |
| 1950 | + if ($sep =~ /%y/) { |
| 1951 | + my $ysep = '-' x (78 - (length ($sep)-2)); $sep =~ s/%y/$ysep/; |
| 1952 | + } |
| 1953 | + print "$hdr\n$sep\n"; |
| 1954 | + } |
| 1955 | + if ($o{listhtml}) { |
| 1956 | + print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\""; |
| 1957 | + print "\n \"http://www.w3.org/TR/html4/loose.dtd\">\n"; |
| 1958 | + print "<html>\n<head>\n"; |
| 1959 | + print "<title>PCA report for $u{hostname}</title>\n"; |
| 1960 | + print "</head>\n<body>\n"; |
| 1961 | + print "<h2>Host: $u{hostname} ($u{osname} $u{osrel}/$u{osversion}/$u{arch}/$u{model})<br>\n"; |
| 1962 | + if ($o{root}) { my $r=$o{root}; $r =~ s/-R //; print "Root: $r<br>\n" } |
| 1963 | + print "List: @slist</h2>\n<table>\n"; |
| 1964 | + (@plist) || return; |
| 1965 | + |
| 1966 | + print "<tr><th>Patch</th>"; |
| 1967 | + print "<th><span title='Installed Revision'>IR</span></th><th></th>"; |
| 1968 | + print "<th><span title='Current Revision'>CR</span></th>"; |
| 1969 | + print "<th><span title='Recommended/Security/Bad Status'>RSB</span></th>"; |
| 1970 | + print "<th>Age</th>"; |
| 1971 | + print "<th>Synopsis</th></tr>\n"; |
| 1972 | + } |
| 1973 | +} |
| 1974 | + |
| 1975 | +sub print_footer { |
| 1976 | + if ($o{listhtml}) { |
| 1977 | + print "</table>\n</body>\n</html>\n"; |
| 1978 | + } |
| 1979 | +} |
| 1980 | + |
| 1981 | +sub get_readme { |
| 1982 | + my $pp=$_[0]; |
| 1983 | + my ($id, $rev)= split (/-/, $pp); |
| 1984 | + |
| 1985 | + my $rfile="$o{tmpdir}/README.$pp" . time() . $$; |
| 1986 | + $p{$id}{dlfile}=$rfile; |
| 1987 | + out ('stderr', "Downloading README for $pp"); |
| 1988 | + |
| 1989 | + # If patch is available in unzipped format, use its README |
| 1990 | + if (-f "$o{patchdir}/$pp/README.$pp") { |
| 1991 | + out ('stderr', "Trying $o{patchdir}/$pp"); |
| 1992 | + copy ("$o{patchdir}/$pp/README.$pp", $rfile); |
| 1993 | + if (-s $rfile) { goto DONE } else { out ('stderr', "Failed") } |
| 1994 | + } |
| 1995 | + # If we have the zip/jar file, extract README from there. This doesn't work |
| 1996 | + # for tar/tar.Z files, as Sun's tar cannot extract files to stdout. |
| 1997 | + foreach my $ext ('zip', 'jar') { |
| 1998 | + if ((-f "$o{patchdir}/$pp.$ext") && !$o{pforce}) { |
| 1999 | + out ('stderr', "Trying $o{patchdir}/$pp.$ext"); |
| 2000 | + `$unzip -p $o{patchdir}/$pp.$ext $pp/README.$pp >$rfile 2>/dev/null`; |
| 2001 | + if (!$? && (-s $rfile)) { goto DONE } else { out ('stderr', "Failed") } |
| 2002 | + } |
| 2003 | + } |
| 2004 | + # Get README from local patch server |
| 2005 | + if ($o{patchurl} =~ /^file:/) { |
| 2006 | + out ('stderr', "Trying $o{patchurl}"); |
| 2007 | + my $path=$o{patchurl}; $path =~ s/^file://; |
| 2008 | + (-r "$path/README.$pp") && copy ("$path/README.$pp", $rfile); |
| 2009 | + if (-s $rfile) { goto DONE } else { out ('stderr', "Failed") } |
| 2010 | + } |
| 2011 | + # Without wget we can't download the README |
| 2012 | + if (!$o{wget}) { |
| 2013 | + out ('info', "Failed (can't find wget executable)"); goto FAIL; |
| 2014 | + } |
| 2015 | + if ($o{patchurl} =~ /^http:|^https:|^ftp/) { |
| 2016 | + out ('stderr', "Trying $o{patchurl}"); |
| 2017 | + if (download("readme", $pp, "local", $rfile, "")) { goto DONE } else { out ('stderr', "Failed") } |
| 2018 | + } |
| 2019 | + # Try download from restricted patch server, if the user provided |
| 2020 | + # Sun Online Account data |
| 2021 | + if (checksoa()) { |
| 2022 | + my $try=1; my $ret=0; |
| 2023 | + while ($try <= $o{dltries}) { |
| 2024 | + out ('stderr', "Trying $o{ssprot}://$o{sshost}/ ($try/$o{dltries})"); |
| 2025 | + $ret=download("readme", $pp, "sunsolve", $rfile, ""); |
| 2026 | + last if $ret; |
| 2027 | + $try++; if ($try <= $o{dltries}) { sleep ($try*2) } |
| 2028 | + } |
| 2029 | + if ($ret) { goto DONE } else { out ('stderr', "Failed") } |
| 2030 | + } else { |
| 2031 | + out ('stderr', "Failed (no Sun Online Account data)"); |
| 2032 | + } |
| 2033 | +FAIL: |
| 2034 | + out ('info', "Failed (README not found)"); |
| 2035 | +DONE: |
| 2036 | + $p{$id}{dlfile}=""; |
| 2037 | + |
| 2038 | + if (-s $rfile) { |
| 2039 | + out ('stderr', "Done"); |
| 2040 | + return ($rfile); |
| 2041 | + } |
| 2042 | + unlink ($rfile); |
| 2043 | + return (); |
| 2044 | +} |
| 2045 | + |
| 2046 | +sub update { |
| 2047 | + if ($o{update} eq "never") { |
| 2048 | + dbg ("Never update"); |
| 2049 | + return; |
| 2050 | + } |
| 2051 | + if (($o{update} ne "auto") && $o{proxy}) { |
| 2052 | + dbg ("update option $o{update} not supported in proxy mode"); |
| 2053 | + return; |
| 2054 | + } |
| 2055 | + |
| 2056 | + # If we can't write to pca, update won't work. |
| 2057 | + if (($o{update} eq 'now') || ($o{update} eq 'auto')) { |
| 2058 | + if (! -w $0) { err ("Update option unavailable: Can't write to $0") } |
| 2059 | + } |
| 2060 | + |
| 2061 | + if ($o{update} eq 'auto') { |
| 2062 | + dbg ("Auto update"); |
| 2063 | + my $interval=86400; # One day |
| 2064 | + my $current=(stat($0))[9]; |
| 2065 | + my $now=time(); |
| 2066 | + my $age=$now-$current; |
| 2067 | + dbg ("pca now : " . localtime($now)); |
| 2068 | + dbg ("pca current: " . localtime($current)); |
| 2069 | + dbg ("pca age : " . $age); |
| 2070 | + if ($age < $interval) { |
| 2071 | + dbg ("age lower than interval"); |
| 2072 | + return; |
| 2073 | + } |
| 2074 | + } |
| 2075 | + |
| 2076 | + my $udir= "$o{tmpdir}/pca." . time() . $$; |
| 2077 | + mkdir $udir,0755 || err ("Can't create temporary directory $udir ($!)"); |
| 2078 | + my $ufile= "$udir/pca"; |
| 2079 | + dbg ("ufile: $ufile"); |
| 2080 | + |
| 2081 | + # Copy pca to temporary directory, keeping the timestamps. |
| 2082 | + my ($atime, $mtime) = (stat($0))[8..9]; |
| 2083 | + copy ($0, $ufile); |
| 2084 | + utime $atime, $mtime, $ufile; |
| 2085 | + |
| 2086 | + my $ret; |
| 2087 | + if ($o{pcaurl} =~ /^http.*pca-proxy\.cgi/) { |
| 2088 | + $ret=download('pca', '', 'pcaurl', "$udir/pca", ""); |
| 2089 | + } else { |
| 2090 | + $ret=download('pca', '', 'pcaurl', "", $udir); |
| 2091 | + } |
| 2092 | + $ret || err ("Could not get pca from $o{pcaurl}"); |
| 2093 | + |
| 2094 | + my $newv; |
| 2095 | + open (F, "<$ufile"); |
| 2096 | + while (<F>) { |
| 2097 | + if ($_ =~ /^my \$version=\'(\d{8}-\d{2})\'/) { |
| 2098 | + $newv=$1; |
| 2099 | + dbg ("Old version: $version"); |
| 2100 | + dbg ("New version: $newv"); |
| 2101 | + last; |
| 2102 | + } |
| 2103 | + } |
| 2104 | + close (F); |
| 2105 | + |
| 2106 | + my $updated=0; |
| 2107 | + if ($newv eq $version) { |
| 2108 | + if ($o{update} eq "auto") { |
| 2109 | + my $now=time(); utime $now, $now, $0; |
| 2110 | + } else { |
| 2111 | + out ('info', "No new version available"); |
| 2112 | + } |
| 2113 | + } else { |
| 2114 | + out ('info', "New version available: $newv (current version: $version)"); |
| 2115 | + if (!$o{proxy}) { |
| 2116 | + out ('info', "\nChanges:\n"); |
| 2117 | + open (F, "<$ufile"); |
| 2118 | + while (<F>) { |
| 2119 | + if ($_ =~ /=head2 Version $newv/) { |
| 2120 | + out ('info', "Version $newv"); |
| 2121 | + while (<F>) { |
| 2122 | + if ($_ =~ /=head2 Version (\d{8}-\d{2})/) { |
| 2123 | + ($1 le $version) && last; |
| 2124 | + } |
| 2125 | + $_ =~ s/=head2 //; chomp; |
| 2126 | + out ('info', "$_"); |
| 2127 | + } |
| 2128 | + } |
| 2129 | + } |
| 2130 | + close (F); |
| 2131 | + } |
| 2132 | + if ($o{update} ne "check") { |
| 2133 | + out ('info', "Update"); |
| 2134 | + dbg ("Copy $ufile to $0"); |
| 2135 | + if (!copy ($ufile, $0)) { |
| 2136 | + out ('info', "Failed ($!)"); |
| 2137 | + } else { |
| 2138 | + out ('info', "Done"); |
| 2139 | + } |
| 2140 | + $updated=1; |
| 2141 | + } |
| 2142 | + } |
| 2143 | + |
| 2144 | + unlink ($ufile); |
| 2145 | + rmdir ($udir); |
| 2146 | + |
| 2147 | + if (($o{update} eq "auto") && !$updated) { return } |
| 2148 | + if ($o{proxy}) { return } |
| 2149 | + exit 0; |
| 2150 | +} |
| 2151 | + |
| 2152 | +sub out { |
| 2153 | + my $cat= shift; |
| 2154 | + |
| 2155 | + if ($o{proxy}) { |
| 2156 | + if ($cat eq 'error') { |
| 2157 | + print "Content-type: text/plain\n"; |
| 2158 | + print "Status: 500 @_\n\n"; |
| 2159 | + print "Internal Error: @_\n"; |
| 2160 | + return; |
| 2161 | + } |
| 2162 | + if ($o{debug}) { |
| 2163 | + open (F, ">> $o{dbgfile}"); |
| 2164 | + my $now= localtime; |
| 2165 | + print F $now, ": ", @_, "\n"; |
| 2166 | + close (F); |
| 2167 | + return |
| 2168 | + } |
| 2169 | + return; |
| 2170 | + } |
| 2171 | + if ($cat eq 'debug' ) { |
| 2172 | + if ($o{debug}) { print "@_\n" } |
| 2173 | + return |
| 2174 | + } |
| 2175 | + if ($o{noheader}) { return } |
| 2176 | + if ($cat eq 'stderr') { print STDERR @_, "\n"; return } |
| 2177 | + if ($cat eq 'info' ) { print @_, "\n"; return } |
| 2178 | + if ($cat eq 'error' ) { print STDERR "\nERROR: ", @_, "\n"; return } |
| 2179 | +} |
| 2180 | + |
| 2181 | +sub dbg { |
| 2182 | + $o{debug} || return; |
| 2183 | + out ('debug', @_); |
| 2184 | +} |
| 2185 | + |
| 2186 | +sub calculateage { |
| 2187 | + my ($tmonth, $day, $year)=split(/\//, $_[0]); |
| 2188 | + my %months=("Jan",0,"Feb",1,"Mar",2,"Apr",3,"May",4,"Jun",5,"Jul",6,"Aug",7,"Sep",8,"Oct",9,"Nov",10,"Dec",11); |
| 2189 | + my $month=$months{$tmonth}; |
| 2190 | + |
| 2191 | + return (int(($currenttime-timelocal(0,0,0,$day,$month,$year))/86400)); |
| 2192 | +} |
| 2193 | + |
| 2194 | +sub lock_create { |
| 2195 | + my $lockd=$_[0]; my $tag=$_[1]; my $maxretry=$_[2]; |
| 2196 | + my $lockf="$lockd/.pcaLock.$tag"; |
| 2197 | + |
| 2198 | + lock_free ($lockd, $tag, $maxretry) || return (0); |
| 2199 | + |
| 2200 | + unlink "$lockf"; |
| 2201 | + sysopen (LOCKF, $lockf, O_RDWR|O_CREAT|O_EXCL) || err ("Can't write $lockf ($!)"); |
| 2202 | + print LOCKF "$$\n"; |
| 2203 | + close LOCKF; |
| 2204 | + chmod 0666, $lockf; |
| 2205 | + $locks{$tag}=$lockf; |
| 2206 | + return (1); |
| 2207 | +} |
| 2208 | + |
| 2209 | +sub lock_free { |
| 2210 | + my $lockd=$_[0]; my $tag=$_[1]; my $maxretry=$_[2]; |
| 2211 | + my $lockf="$lockd/.pcaLock.$tag"; |
| 2212 | + |
| 2213 | + my $retry=0; |
| 2214 | + while ($retry < $maxretry) { |
| 2215 | + if (-s "$lockf") { |
| 2216 | + open (LOCKF, "<$lockf"); |
| 2217 | + chomp(my $pid = <LOCKF>); |
| 2218 | + close LOCKF; |
| 2219 | + if (kill (0, $pid) || ($! eq "Not owner")) { |
| 2220 | + dbg ("Locking $lockf failed"); |
| 2221 | + $retry++; |
| 2222 | + ($retry < $maxretry) && sleep (1); |
| 2223 | + next; |
| 2224 | + } |
| 2225 | + } |
| 2226 | + return (1); |
| 2227 | + } |
| 2228 | + return (0); |
| 2229 | +} |
| 2230 | + |
| 2231 | +sub lock_remove { |
| 2232 | + my $lockd=$_[0]; |
| 2233 | + my $tag=$_[1]; |
| 2234 | + |
| 2235 | + unlink "$locks{$tag}"; |
| 2236 | + $locks{$tag}=''; |
| 2237 | +} |
| 2238 | + |
| 2239 | +sub log_msg { |
| 2240 | + ($o{syslog}) && system("$o{logger} -t pca -p $o{syslog}.info \"@_\""); |
| 2241 | +} |
| 2242 | + |
| 2243 | +sub err { |
| 2244 | + out ('error', @_); |
| 2245 | + cleanup(); |
| 2246 | + exit 1; |
| 2247 | +} |
| 2248 | + |
| 2249 | +sub handler { |
| 2250 | + err ("Caught a SIG@_"); |
| 2251 | +} |
| 2252 | + |
| 2253 | +sub cleanup { |
| 2254 | + dbg ("Cleanup"); |
| 2255 | + if ($dlfile) { |
| 2256 | + dbg ("Removing $dlfile"); |
| 2257 | + unlink "$dlfile"; |
| 2258 | + } |
| 2259 | + if (($input{xref}) && (-s "$input{xref}.tmp")) { |
| 2260 | + dbg ("Putting back copy of patchdiag.xref file"); |
| 2261 | + rename ("$input{xref}.tmp", "$input{xref}"); |
| 2262 | + } |
| 2263 | + foreach my $id (keys %p) { |
| 2264 | + if ($p{$id}{dlfile}) { |
| 2265 | + dbg ("Removing $p{$id}{dlfile}"); |
| 2266 | + unlink "$p{$id}{dlfile}"; |
| 2267 | + } |
| 2268 | + } |
| 2269 | + if (@rlist) { |
| 2270 | + dbg ("Removing @rlist"); |
| 2271 | + unlink (@rlist); |
| 2272 | + } |
| 2273 | + $patchxdir && rmtree ($patchxdir); |
| 2274 | + foreach my $tag (keys %locks) { |
| 2275 | + if ($locks{$tag}) { |
| 2276 | + dbg ("Removing $locks{$tag}"); |
| 2277 | + unlink "$locks{$tag}"; |
| 2278 | + } |
| 2279 | + } |
| 2280 | + $sttyset && system "stty echo"; |
| 2281 | +} |
| 2282 | + |
| 2283 | +sub base64 { |
| 2284 | + # From MIME-Base64-Perl-1.00 |
| 2285 | + |
| 2286 | + my $res = pack("u", $_[0]); |
| 2287 | + # Remove first character of each line, remove newlines |
| 2288 | + $res =~ s/^.//mg; $res =~ s/\n//g; |
| 2289 | + |
| 2290 | + $res =~ tr|` -_|AA-Za-z0-9+/|; |
| 2291 | + # fix padding at the end |
| 2292 | + my $padding = (3 - length($_[0]) % 3) % 3; |
| 2293 | + $res =~ s/.{$padding}$/'=' x $padding/e if $padding; |
| 2294 | + return $res; |
| 2295 | +} |
| 2296 | + |
| 2297 | +sub parse_args { |
| 2298 | + # Get internal defaults |
| 2299 | + foreach my $opt (@options) { |
| 2300 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2301 | + if ($long eq 'cffile') { |
| 2302 | + map { read_cffile($_) } split (/ /, $default); |
| 2303 | + } elsif ($arg =~ /@/) { |
| 2304 | + @{$o{$long}}=split (/ /, $default); |
| 2305 | + } else { |
| 2306 | + $o{$long}=$default; |
| 2307 | + } |
| 2308 | + } |
| 2309 | + (basename($0) eq "pca-proxy.cgi") && ($o{proxy}=1); |
| 2310 | + (basename($0) =~ "debug") && ($o{debug}=1); |
| 2311 | + $o{proxy} && ($o{xrefdir} = getcwd()); |
| 2312 | + |
| 2313 | + # Get defaults from optional configuration file(s) |
| 2314 | + my @conf=(); |
| 2315 | + push (@conf, dirname($0)."/pca.conf"); |
| 2316 | + push (@conf, dirname($0)."/../etc/pca.conf"); |
| 2317 | + push (@conf, "/etc/pca.conf"); |
| 2318 | + $ENV{HOME} && push (@conf, $ENV{HOME}."/.pca"); |
| 2319 | + push (@conf, "pca.conf"); |
| 2320 | + if ($o{proxy}) { |
| 2321 | + push (@conf, dirname($0)."/../etc/pca-proxy.conf"); |
| 2322 | + push (@conf, "/etc/pca-proxy.conf"); |
| 2323 | + push (@conf, "pca-proxy.conf"); |
| 2324 | + } |
| 2325 | + foreach my $i (@conf) { read_cffile ($i) } |
| 2326 | + |
| 2327 | + # Get defaults from optional environment variables (PCA_*) |
| 2328 | + foreach my $opt (@options) { |
| 2329 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2330 | + next if ($help eq "INTERNAL"); |
| 2331 | + my $env=uc("PCA_$long"); |
| 2332 | + next unless ($ENV{$env}); |
| 2333 | + if ($long eq 'cffile') { |
| 2334 | + map { read_cffile($_) } split (/ /, $ENV{$env}); |
| 2335 | + } elsif ($arg =~ /@/) { |
| 2336 | + push (@{$o{$long}}, split (/ /, $ENV{$env})) |
| 2337 | + } else { |
| 2338 | + $o{$long}=$ENV{$env} |
| 2339 | + } |
| 2340 | + } |
| 2341 | + ($ENV{TMPDIR}) && (-d $ENV{TMPDIR}) && ($o{tmpdir}= $ENV{TMPDIR}); |
| 2342 | + |
| 2343 | + # Proxy mode ? |
| 2344 | + if ($o{proxy}) { |
| 2345 | + if ($#ARGV != 0) { err ("Missing argument") } |
| 2346 | + if ($ARGV[0] =~ /:force/) { $ARGV[0] =~ s/:force//; $o{pforce}=1 } |
| 2347 | + if ((($ARGV[0] !~ /^patchdiag.xref$/) && |
| 2348 | + ($ARGV[0] !~ /^\d{6}-\d{2}\.(zip|jar|tar|tar\.Z)$/) && |
| 2349 | + ($ARGV[0] !~ /^\d{6}-\d{2}$/) && |
| 2350 | + ($ARGV[0] !~ /^README\.\d{6}-\d{2}$/) && |
| 2351 | + ($ARGV[0] !~ /^pca$/))) { |
| 2352 | + err ("Illegal argument"); |
| 2353 | + } |
| 2354 | + $o{proxy}=$ARGV[0]; |
| 2355 | + } else { |
| 2356 | + # Get command line options |
| 2357 | + my @olist=(); |
| 2358 | + foreach my $opt (@options) { |
| 2359 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2360 | + next if (($help eq "INTERNAL") || ($help eq "ENVFILE")); |
| 2361 | + $short && ($long="$long|$short"); |
| 2362 | + if ($arg) { $long .= "=$arg" } elsif ($Getopt::Long::VERSION >= 2.32) { $long .= "!" } |
| 2363 | + push (@olist, $long); |
| 2364 | + } |
| 2365 | + Getopt::Long::config ("bundling", "no_ignore_case"); |
| 2366 | + $o{cffile}=sub { read_cffile ($_[1]) }; |
| 2367 | + GetOptions (\%o, @olist) || usage() && exit 1; |
| 2368 | + delete $o{cffile}; |
| 2369 | + } |
| 2370 | + if ($o{help}) { usage(); exit 0 } |
| 2371 | + if ($o{man}) { man(); exit 0 } |
| 2372 | + if ($o{version}) { version(); exit 0 } |
| 2373 | + |
| 2374 | + $o{listhtml} && ($o{list}=1); |
| 2375 | + $o{pretend} && ($o{install}=1); |
| 2376 | + $o{root} && ($o{root}="-R $o{root}"); |
| 2377 | + if (!$o{patchurl} && $o{localurl}) { $o{patchurl}=$o{localurl} } |
| 2378 | + if (!$o{xrefurl} && $o{localurl}) { $o{xrefurl}=$o{localurl} } |
| 2379 | + if ($o{patchurl} =~ /\.cgi$/) { $o{patchurl} .= "?" } |
| 2380 | + if ($o{xrefurl} =~ /\.cgi$/) { $o{xrefurl} .= "?" } |
| 2381 | + if ($o{pcaurl} =~ /\.cgi$/) { $o{pcaurl} .= "?" } |
| 2382 | + if ($o{patchurl} =~ /[^\/\?]$/) { $o{patchurl} .= "/" } |
| 2383 | + if ($o{xrefurl} =~ /[^\/\?]$/) { $o{xrefurl} .= "/" } |
| 2384 | + if ($o{pcaurl} =~ /[^\/\?]$/) { $o{pcaurl} .= "/" } |
| 2385 | + ($o{patchdir} !~ /^(\/|\w:\/)/) && ($o{patchdir}= getcwd()."/$o{patchdir}"); |
| 2386 | + ($o{xrefdir} !~ /^(\/|\w:\/)/) && ($o{xrefdir}= getcwd()."/$o{xrefdir}"); |
| 2387 | + |
| 2388 | + # Set defaults |
| 2389 | + $o{operands} && !@ARGV && (@ARGV=(split (/\s+/, $o{operands}))); |
| 2390 | + ($o{download} || $o{install} || $o{readme} || $o{getxref} || $o{proxy}) || ($o{list}=1); |
| 2391 | + |
| 2392 | + # Show all options and configuration files in debug output |
| 2393 | + foreach my $opt (@options) { |
| 2394 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2395 | + if ($long eq 'cffile') { |
| 2396 | + } elsif ($arg =~ /@/) { |
| 2397 | + next unless (@{$o{$long}}); |
| 2398 | + dbg ("Option $long: @{$o{$long}}"); |
| 2399 | + } else { |
| 2400 | + next if ($o{$long} eq $default); |
| 2401 | + dbg ("Option $long: $o{$long}") |
| 2402 | + } |
| 2403 | + } |
| 2404 | + dbg ("ARGV: @ARGV"); |
| 2405 | + dbg ("Version: $version"); |
| 2406 | + ($conf_dbg) && dbg ("Config files: $conf_dbg"); |
| 2407 | + |
| 2408 | + if ($o{update} !~ /^(never|check|now|auto)$/) { |
| 2409 | + err ("Invalid TYPE specified with --update: $o{update}"); |
| 2410 | + } |
| 2411 | +} |
| 2412 | + |
| 2413 | +sub process_patch_exceptions { |
| 2414 | + foreach my $i ('stop', 'ignore', 'nobackup') { |
| 2415 | + foreach my $j (@{$o{$i}}) { |
| 2416 | + #dbg ("$i: $j"); |
| 2417 | + if ($j =~ /^all$/) { $o{$i}='all'; last } |
| 2418 | + if ($j =~ /^(\d{6})$/) { init_patch($1); ($p{$1}{$i}= "00"); next } |
| 2419 | + if ($j =~ /^(\d{6})-(\d{2})$/) { init_patch($1); ($p{$1}{$i}= $2); next } |
| 2420 | + err ("Invalid patch ID with --$i: $j") |
| 2421 | + } |
| 2422 | + } |
| 2423 | +} |
| 2424 | + |
| 2425 | +sub process_patch_flags { |
| 2426 | + foreach my $i ('rec', 'sec') { |
| 2427 | + foreach my $j (@{$o{$i}}) { |
| 2428 | + #dbg ("$i: $j"); |
| 2429 | + if ($j =~ /^(\d{6})(-\d{2})*$/) { init_patch($1); ($p{$1}{"${i}f"}= 1); next } |
| 2430 | + err ("Invalid patch ID with --$i: $j") |
| 2431 | + } |
| 2432 | + } |
| 2433 | +} |
| 2434 | + |
| 2435 | +sub read_cffile { |
| 2436 | + if ($conf_read{$_[0]}) { return } else { $conf_read{$_[0]}=1 } |
| 2437 | + local *CONF; |
| 2438 | + open (CONF, "<$_[0]") || return; |
| 2439 | + $conf_dbg .= "$_[0] "; dbg ("Reading cffile $_[0]"); |
| 2440 | + while (<CONF>) { |
| 2441 | + chomp; |
| 2442 | + s/^#.*$//; s/\s+#.*$//; s/^\s*//; s/\s*$//; |
| 2443 | + next if /^$/; |
| 2444 | + |
| 2445 | + # Deprecated |
| 2446 | + if (/(\d{6})\s+ignore/) { push (@{$o{ignore}}, $1); next } |
| 2447 | + if (/(\d{6}-\d{2})\s+ignore/) { push (@{$o{ignore}}, $1); next } |
| 2448 | + if (/(\d{6})\s+\+rec/) { push (@{$o{rec}}, $1); next } |
| 2449 | + if (/(\d{6})\s+\+sec/) { push (@{$o{sec}}, $1); next } |
| 2450 | + |
| 2451 | + next unless (/(\w+)\s*=\s*(.+)/); my ($name, $value)=($1,$2); |
| 2452 | + foreach my $opt (@options) { |
| 2453 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2454 | + next if ($help eq "INTERNAL"); |
| 2455 | + next unless ($name eq $long); |
| 2456 | + if ($long eq 'cffile') { |
| 2457 | + map { read_cffile($_) } split (/ /, $value); |
| 2458 | + } elsif ($arg =~ /@/) { |
| 2459 | + push (@{$o{$long}}, split (/ /, $value)) |
| 2460 | + } else { |
| 2461 | + $o{$long}=$value |
| 2462 | + } |
| 2463 | + last |
| 2464 | + } |
| 2465 | + } |
| 2466 | +} |
| 2467 | + |
| 2468 | +sub usage { |
| 2469 | + print<<EOT |
| 2470 | +Usage: $0 [OPTION] .. [OPERAND] .. |
| 2471 | + |
| 2472 | +Operands: |
| 2473 | + patch group: missing, installed, all, total, unbundled, bad |
| 2474 | + Add r, s or rs at the end to list Recommended, |
| 2475 | + Security or Recommended/Security patches only. |
| 2476 | + patch ID: 123456, 123456-78 |
| 2477 | + patch file: 123456-78.zip, 123456-78.jar, 123456-78.tar.Z |
| 2478 | + file name: patchlist.txt |
| 2479 | + |
| 2480 | +Options: |
| 2481 | + |
| 2482 | +EOT |
| 2483 | +; |
| 2484 | + |
| 2485 | + foreach my $opt (@options) { |
| 2486 | + my ($long, $short, $arg, $argtxt, $default, $help)=split (/\|/, $opt); |
| 2487 | + next if (($help eq "INTERNAL") || ($help eq "ENVFILE") || ($help eq "DEPRECATED")); |
| 2488 | + $short && ($short="-$short,"); |
| 2489 | + $argtxt && ($long="$long=$argtxt"); |
| 2490 | + printf " %3s --%-15s%s\n", $short, $long, $help; |
| 2491 | + } |
| 2492 | + return 1; |
| 2493 | +} |
| 2494 | + |
| 2495 | +sub man { |
| 2496 | + eval "use Pod::Usage"; |
| 2497 | + if ($@) { err ('Required module Pod::Usage not found') } |
| 2498 | + |
| 2499 | + # Change uid to something secure as pod2usage does not run as root. |
| 2500 | + # This snippet is taken from perldoc. See the comments there. |
| 2501 | + my $id= eval { getpwnam("nobody") }; |
| 2502 | + $id= eval { getpwnam("nouser") } unless defined $id; |
| 2503 | + $id= -2 unless defined $id; |
| 2504 | + eval { |
| 2505 | + $< = $id; # real uid |
| 2506 | + $> = $id; # effective uid |
| 2507 | + $< = $id; # real uid |
| 2508 | + $> = $id; # effective uid |
| 2509 | + }; |
| 2510 | + pod2usage( -exitstatus => 0, -verbose => 2 ); |
| 2511 | +} |
| 2512 | + |
| 2513 | +sub version { |
| 2514 | + print "pca $version\n"; |
| 2515 | +} |
| 2516 | + |
| 2517 | +__END__ |
| 2518 | + |
| 2519 | +=head1 NAME |
| 2520 | + |
| 2521 | +pca - analyze, download and install patches for Sun Solaris |
| 2522 | + |
| 2523 | +=head1 SYNOPSIS |
| 2524 | + |
| 2525 | +pca [OPTION] .. [OPERAND] .. |
| 2526 | + |
| 2527 | +=head1 DESCRIPTION |
| 2528 | + |
| 2529 | +pca is a perl script which generates lists of installed and missing |
| 2530 | +patches for Sun Solaris systems and optionally downloads and installs |
| 2531 | +patches. By default, if run without any option or operand, pca |
| 2532 | +shows a list of all patches which are not installed in their most recent |
| 2533 | +revision. |
| 2534 | + |
| 2535 | +The output of the pkginfo, showrev and uname commands is used to gather |
| 2536 | +information about the system. Sun offers a patch cross-reference file |
| 2537 | +called patchdiag.xref which contains information about all available patches. |
| 2538 | +This file is downloaded by pca automatically to /var/tmp/ and kept up-to-date. |
| 2539 | +If the file |
| 2540 | +exists and is not writable, pca uses it and won't try to update it. |
| 2541 | + |
| 2542 | +=head1 SAMPLE OUTPUT |
| 2543 | + |
| 2544 | +Here's some sample output from I<pca -l all>, which shows a list |
| 2545 | +of all installed and missing patches: |
| 2546 | + |
| 2547 | + Host: myhost (SunOS 5.9/Generic_117171-09/sparc/sun4u) |
| 2548 | + List: all |
| 2549 | + |
| 2550 | + Patch IR CR RSB Age Synopsis |
| 2551 | + ------ -- - -- --- --- -------------------------------------------------- |
| 2552 | + 112785 42 < 43 RS- 18 X11 6.6.1: Xsun patch |
| 2553 | + 112787 01 = 01 --- 999 X11 6.6.1: twm patch |
| 2554 | + 112807 10 = 10 RS- 9 CDE 1.5: dtlogin patch |
| 2555 | + 113039 -- < 06 --- 76 SAN 4.4.1: Sun StorEdge Traffic Manager patch |
| 2556 | + 113040 -- < 08 R-- 77 SAN 4.4.1: fctl/fp/fcp driver patch |
| 2557 | + 113477 02 > -- --- 999 NOT FOUND IN CROSS REFERENCE FILE! |
| 2558 | + 117114 -- < 02 --- 4 CDE 1.5: sdtwebclient patch |
| 2559 | + |
| 2560 | +The first column (I<Patch>) contains the patch number, followed by the |
| 2561 | +installed revision (I<IR>) and the current revision |
| 2562 | +(I<CR>), with one of E<lt>, E<gt>, or = between |
| 2563 | +them, which tells whether the installed patch revision is lower, equal or |
| 2564 | +higher than the current revision of the patch. The I<RSB> column lists |
| 2565 | +the Recommended/Security/Bad flag of the patch. I<Age> shows the |
| 2566 | +number of days since the patch was released, and |
| 2567 | +I<Synopsis> shows a short description of the patch. |
| 2568 | + |
| 2569 | +On this system, revision 42 of patch 112785 is installed, but a newer |
| 2570 | +revision (43) is available. This patch is marked Recommended/Security. |
| 2571 | +Patch 112787 is installed in revision 01, which is the most |
| 2572 | +recent revision of the patch. |
| 2573 | +112807 is marked Recommended/Security, and it's up-to-date. |
| 2574 | + |
| 2575 | +Patches 113039, 113040 and 117114 are not installed |
| 2576 | +at all, and 113040 is marked Recommended. |
| 2577 | + |
| 2578 | +113477 is installed, but not listed in the cross-reference file. |
| 2579 | +New Solaris update releases often have patches pre-installed which |
| 2580 | +are not yet listed in patchdiag.xref. |
| 2581 | + |
| 2582 | +Often one patch requires other patches to be installed before |
| 2583 | +it can be installed. pca resolves these dependencies, |
| 2584 | +and lists patches in their correct order. This can be seen |
| 2585 | +in the patch list when a greater patch number is shown |
| 2586 | +before a lower one, or when a patch which is not marked R/S is shown |
| 2587 | +on the list of missing R/S patches. |
| 2588 | + |
| 2589 | +=head1 OPTIONS |
| 2590 | + |
| 2591 | +=over 5 |
| 2592 | + |
| 2593 | +=item -l, --list |
| 2594 | + |
| 2595 | +List patches. See OPERANDS on how to specify which patches |
| 2596 | +are listed. |
| 2597 | + |
| 2598 | +=item -L, --listhtml |
| 2599 | + |
| 2600 | +Like I<-l>, but generates output in HTML format, including |
| 2601 | +links to patch READMEs and downloads. If I<patchurl> is set and |
| 2602 | +points at a local patch proxy, the links in HTML output will point there, |
| 2603 | +too. |
| 2604 | + |
| 2605 | +=item -d, --download |
| 2606 | + |
| 2607 | +Download patches. See OPERANDS on how to specify which patches |
| 2608 | +are downloaded. Patches are placed in the current directory or |
| 2609 | +in I<patchdir>, if set. A Sun Online Account is required. |
| 2610 | + |
| 2611 | +=item -i, --install |
| 2612 | + |
| 2613 | +Download and install patches. See OPERANDS on how to specify |
| 2614 | +which patches are installed. Requires pca to be run as root. Downloaded |
| 2615 | +patches are removed after successful installation, unless I<--download> |
| 2616 | +is used, too. |
| 2617 | + |
| 2618 | +=item -I, --pretend |
| 2619 | + |
| 2620 | +Like I<-i>, but only pretend to install patches. Can be used |
| 2621 | +to find out if any of the patches require a reboot. |
| 2622 | + |
| 2623 | +=item -r, --readme |
| 2624 | + |
| 2625 | +Display patch READMEs. See OPERANDS on how to specify |
| 2626 | +which READMEs are displayed. |
| 2627 | +The patch README is |
| 2628 | +extracted from a previously downloaded patch file or downloaded |
| 2629 | +directly from Sun, if Sun Online Account data is provided. |
| 2630 | + |
| 2631 | +=item -x, --getxref |
| 2632 | + |
| 2633 | +Download most recent patch cross-reference file. |
| 2634 | +If the file does not exist or is older than 3 hours, pca tries to |
| 2635 | +download it on its own before anything else. |
| 2636 | + |
| 2637 | +=item -X, --xrefdir=DIR |
| 2638 | + |
| 2639 | +Set location of the cross-reference file. The default is |
| 2640 | +I</var/tmp> (in proxy mode, the default is the current directory). |
| 2641 | +By default, patchdiag.xref is writable for all users. If the I<xrefown> |
| 2642 | +option is set, or the I<xrefdir> option contains I</home>, |
| 2643 | +the cross reference file will be |
| 2644 | +writable by the current user only. |
| 2645 | + |
| 2646 | +=item -y, --nocheckxref |
| 2647 | + |
| 2648 | +Do not check for updated patch cross-reference file. Use this option |
| 2649 | +to maintain a global baseline patch set. |
| 2650 | + |
| 2651 | +=item --xrefown |
| 2652 | + |
| 2653 | +If set, patchdiag.xref will be writable for the current |
| 2654 | +user only. |
| 2655 | + |
| 2656 | +=item --nocache |
| 2657 | + |
| 2658 | +If a proxy is used to access the Internet, this option advises |
| 2659 | +it to not cache patchdiag.xref. Useful if the proxy can't be trusted |
| 2660 | +to always return an up-to-date version of the file. |
| 2661 | + |
| 2662 | +=item -P, --patchdir=DIR |
| 2663 | + |
| 2664 | +Set directory to which patches are downloaded. The default is |
| 2665 | +the current working directory. |
| 2666 | + |
| 2667 | +=item -a, --askauth |
| 2668 | + |
| 2669 | +Ask for Sun Online Account data interactively when needed. |
| 2670 | + |
| 2671 | +=item --user=USER |
| 2672 | + |
| 2673 | +Login name for Sun Online Account authentication. |
| 2674 | + |
| 2675 | +=item --passwd=PASS |
| 2676 | + |
| 2677 | +Password for Sun Online Account authentication. |
| 2678 | + |
| 2679 | +=item --patchurl=URL |
| 2680 | + |
| 2681 | +If set, pca tries to download patches and READMEs from |
| 2682 | +this URL first. Any URL starting with file:/, ftp://, http:// or |
| 2683 | +https:// can be used. See LOCAL PATCH SERVER for more information. |
| 2684 | + |
| 2685 | +=item --xrefurl=URL |
| 2686 | + |
| 2687 | +If set, pca tries to download the patchdiag.xref file from |
| 2688 | +this URL first. Any URL starting with file:/, ftp://, http:// or |
| 2689 | +https:// can be used. See LOCAL PATCH SERVER for more information. |
| 2690 | + |
| 2691 | +=item --localurl=URL |
| 2692 | + |
| 2693 | +Deprecated. Use I<patchurl> and I<xrefurl> instead. |
| 2694 | +If set, pca tries to download patches, READMEs and patchdiag.xref from |
| 2695 | +this URL first. Any URL starting with file:/, ftp://, http:// or |
| 2696 | +https:// can be used. |
| 2697 | + |
| 2698 | +=item --stop=ID |
| 2699 | + |
| 2700 | +Stop after patch ID. When the specified patch ID is reached during |
| 2701 | +listing, downloading or installing patches all operations are stopped. |
| 2702 | + |
| 2703 | +=item --ignore=ID |
| 2704 | + |
| 2705 | +Ignore patch ID. The patch will not be listed, downloaded |
| 2706 | +or installed unless it is required by another patch. Specify a patch ID |
| 2707 | +without revision (I<123456>) to ignore any revision of patch 123456. |
| 2708 | +Specify I<123456-78> to ignore only revision 78 of patch 123456; newer |
| 2709 | +revisions will not be ignored. |
| 2710 | + |
| 2711 | +=item --rec=ID |
| 2712 | + |
| 2713 | +Set Recommended flag on patch ID. Useful to add single patches |
| 2714 | +to the set of recommended patches. The patch will be marked with a lowercase |
| 2715 | +I<r> in pca's output. |
| 2716 | + |
| 2717 | +=item --sec=ID |
| 2718 | + |
| 2719 | +Set Security flag on patch ID. Useful to add single patches |
| 2720 | +to the set of security patches. The patch will be marked with a lowercase |
| 2721 | +I<s> in pca's output. |
| 2722 | + |
| 2723 | +=item -p, --pattern=REGEX |
| 2724 | + |
| 2725 | +List only patches whose synopsis matches the search pattern |
| 2726 | +REGEX. This can be a simple string like I<mail> or a regular |
| 2727 | +expression like I<"[kK]ernel">. If the pattern starts with a |
| 2728 | +'!', only patches which do not match the pattern are shown. |
| 2729 | + |
| 2730 | +=item -n, --noreboot |
| 2731 | + |
| 2732 | +Install only patches that don't require a reboot after |
| 2733 | +installation. |
| 2734 | + |
| 2735 | +=item --minage=DAYS |
| 2736 | + |
| 2737 | +List only patches which are at least DAYS old. |
| 2738 | + |
| 2739 | +=item --maxage=DAYS |
| 2740 | + |
| 2741 | +List only patches which are at most DAYS old. |
| 2742 | + |
| 2743 | +=item --syslog=TYPE |
| 2744 | + |
| 2745 | +Syslog facility (eg. user or local0) to log successful patch |
| 2746 | +installs to. |
| 2747 | + |
| 2748 | +=item -k, --nobackup=ID |
| 2749 | + |
| 2750 | +Do not back up files to be patched for patch ID. This works by running |
| 2751 | +patchadd with its I<-d> option. Patches can not be backed out if this |
| 2752 | +option is used. Specify a patch ID with or without a revision or the |
| 2753 | +special ID "all" to not back up files for any patch. |
| 2754 | + |
| 2755 | +=item -B, --backdir=DIR |
| 2756 | + |
| 2757 | +Saves patch backout data to DIR. This works by running patchadd |
| 2758 | +with its I<-B> option. |
| 2759 | + |
| 2760 | +=item -s, --safe |
| 2761 | + |
| 2762 | +Safe patch installation. Checks all files for local modifications |
| 2763 | +before installing a patch. A patch will not be installed if files with |
| 2764 | +local modifications would be overwritten. |
| 2765 | + |
| 2766 | +=item -G, --currentzone |
| 2767 | + |
| 2768 | +Make patchadd modify packages in the current zone only. This |
| 2769 | +works by running patchadd with its I<-G> option. This option works |
| 2770 | +on Solaris 10 or newer only. |
| 2771 | + |
| 2772 | +=item --patchadd=FILE |
| 2773 | + |
| 2774 | +Path to an alternative patchadd command. |
| 2775 | + |
| 2776 | +=item -H, --noheader |
| 2777 | + |
| 2778 | +Don't display descriptive headers and other information, just one line |
| 2779 | +per patch. Useful if re-using pca's output in own scripts. |
| 2780 | + |
| 2781 | +=item --format=FORMAT |
| 2782 | + |
| 2783 | +Set output format to FORMAT. The default format is |
| 2784 | +"%p %i %e %c %r%s%b %a %y". Use I<%p> for the patch number, |
| 2785 | +I<%i> for the installed revision, I<%e> for information whether |
| 2786 | +the installed revision is lower, equal or higher than the current revision |
| 2787 | +(I<%c>). Use I<%r>, I<%s> and I<%b> for the Recommended, |
| 2788 | +Security and Bad flag, I<%a> for the age and I<%y> for the |
| 2789 | +Synopsis. Use I<%n> as a patch counter and I<%t> for the total |
| 2790 | +number of patches. |
| 2791 | +Example: With the format string "%p-%c %y" pca shows patches |
| 2792 | +in the same format as smpatch. Use of this option in combination with |
| 2793 | +I<--listhtml> is unsupported. |
| 2794 | + |
| 2795 | +=item -f, --fromfiles=DIR |
| 2796 | + |
| 2797 | +Read uname/showrev/pkginfo output from files in the specified |
| 2798 | +directory, where DIR can also be a file name prefix. See |
| 2799 | +CREATING PATCH REPORTS FOR REMOTE MACHINES for details. |
| 2800 | + |
| 2801 | +=item --dltries=NUM |
| 2802 | + |
| 2803 | +Try downloads from Sun's download server NUM times. The |
| 2804 | +default is 1. Can be raised to reduce failed patch downloads when |
| 2805 | +Sun's patch download server is unresponsive. |
| 2806 | + |
| 2807 | +=item -F, --force |
| 2808 | + |
| 2809 | +Force local caching proxy to download patchdiag.xref, patches |
| 2810 | +and patch READMEs from Sun's download server, even if the file is already |
| 2811 | +in the cache. Useful to download updated patch READMEs for bad |
| 2812 | +patches. |
| 2813 | + |
| 2814 | +=item -R, --root=DIR |
| 2815 | + |
| 2816 | +Set alternative root directory. This can be useful for Live Upgrade, |
| 2817 | +to analyze patches in an alternate root environment or to point pca at |
| 2818 | +the mini-root of a jumpstart install server. |
| 2819 | + |
| 2820 | +=item --wget=FILE |
| 2821 | + |
| 2822 | +Path to the wget command. |
| 2823 | + |
| 2824 | +=item --wgetproxy=URL |
| 2825 | + |
| 2826 | +Default proxy for wget. |
| 2827 | + |
| 2828 | +=item --logger=FILE |
| 2829 | + |
| 2830 | +Path to (alternative) logger command. |
| 2831 | + |
| 2832 | +=item -t, --threads=NUM |
| 2833 | + |
| 2834 | +Number of concurrent download threads. See THREADS for details. |
| 2835 | + |
| 2836 | +=item --update=TYPE |
| 2837 | + |
| 2838 | +Check for available updates for pca itself. TYPE can be I<never>, I<check>, |
| 2839 | +I<now> or I<auto>. See UPDATE PCA for more information. |
| 2840 | + |
| 2841 | +=item --pcaurl=URL |
| 2842 | + |
| 2843 | +Set the URL which is used by I<update> to check for new versions of pca. |
| 2844 | +See UPDATE PCA for more information. |
| 2845 | + |
| 2846 | +=item --ssprot=PROT |
| 2847 | + |
| 2848 | +Use PROT as the protocol to access the Sun download server. The default |
| 2849 | +is I<http>. The only reasonable alternative value is I<https>; wget must |
| 2850 | +support HTTPS for this to work. |
| 2851 | + |
| 2852 | +=item --sshost=HOST |
| 2853 | + |
| 2854 | +Use HOST as the hostname or IP address of the Sun download server. |
| 2855 | +The default is I<sunsolve.sun.com>. |
| 2856 | + |
| 2857 | +=item --cffile=FILE |
| 2858 | + |
| 2859 | +Read FILE as additional configuration file. Use I<cffile=FILE> in a |
| 2860 | +configuration file to include FILE. |
| 2861 | + |
| 2862 | +=item -V, --debug |
| 2863 | + |
| 2864 | +Show debug output. This includes output generated by patchadd. When |
| 2865 | +running in proxy mode, debug output will be written to the file |
| 2866 | +/tmp/pca-proxy-debug.txt. |
| 2867 | + |
| 2868 | +=item -h, --help |
| 2869 | + |
| 2870 | +Print help on command line options. |
| 2871 | + |
| 2872 | +=item -m, --man |
| 2873 | + |
| 2874 | +Print manual page. This requires the Pod::Usage module. |
| 2875 | + |
| 2876 | +=item -v, --version |
| 2877 | + |
| 2878 | +Print version information. |
| 2879 | + |
| 2880 | +=back |
| 2881 | + |
| 2882 | +If no option is specified, the I<-l> option to list patches is used. |
| 2883 | + |
| 2884 | +=head1 OPERANDS |
| 2885 | + |
| 2886 | +The operands determine which patches are listed (I<-l>), |
| 2887 | +downloaded (I<-d>), installed (I<-i>) or whose READMEs |
| 2888 | +are displayed (I<-r>). Multiple operands |
| 2889 | +can be specified. Supported operands |
| 2890 | +are I<patch group> (missing, installed, all, total, unbundled, bad), |
| 2891 | +I<patch ID> with or without revision |
| 2892 | +(123456-78 or 123456), I<patch file> (123456-78.zip) and |
| 2893 | +I<file name> (patchlist.txt). |
| 2894 | + |
| 2895 | +The patch groups can be used to specify all missing patches (I<missing>), |
| 2896 | +all installed patches (I<installed>), both installed and missing patches |
| 2897 | +(I<all>), all patches listed in patchdiag.xref (I<total>), |
| 2898 | +patches not associated with a software package (I<unbundled>) |
| 2899 | +or installed patches which are marked Bad (I<bad>). |
| 2900 | +By adding I<r>, I<s> or I<rs> to any of |
| 2901 | +the patch groups, only patches from the patch group which are marked |
| 2902 | +Recommended, Security or either Recommended or Security are specified. |
| 2903 | +Examples are I<missings> for all missing Security patches, or |
| 2904 | +I<allrs> for all Recommended/Security patches. |
| 2905 | +Patch groups can be shortened by using the first letter of the patch |
| 2906 | +group plus optional r/s/rs |
| 2907 | +(e.g. I<ms> for missings or I<ars> for allrs). |
| 2908 | + |
| 2909 | +Patch IDs like I<123456-78> or I<123456> are used to specify |
| 2910 | +single patches. If no revision (I<-78>) is specified, patch dependencies |
| 2911 | +will be resolved. If the name of a patch file like |
| 2912 | +I<123456-78.zip> is specified, it has the same effect as using |
| 2913 | +I<123456-78>. This can be useful to install a list of already |
| 2914 | +downloaded patches with I<pca -i *.zip>. |
| 2915 | + |
| 2916 | +If a I<file name> is specified, the file is read and its |
| 2917 | +contents are added to the list of operands line-by-line. A file |
| 2918 | +can contain other file names. If the file name is equal to a valid |
| 2919 | +patch group name it will not be read. |
| 2920 | + |
| 2921 | +The patch list can be limited to patches whose synopsis line contains |
| 2922 | +a search pattern by using any patch group in combination with the |
| 2923 | +I<--pattern=REGEX> option. |
| 2924 | +A command like I<pca -p mail> shows any missing patch containing |
| 2925 | +the I<mail> keyword in its description. |
| 2926 | +If the search pattern contains whitespace or special characters, enclose |
| 2927 | +it in quotation marks: |
| 2928 | +I<pca -p "Sun Studio" -l total> shows patches for all versions of |
| 2929 | +Sun Studio. If the pattern starts with '!', the patch list is |
| 2930 | +limited to patches which do not match the pattern. |
| 2931 | + |
| 2932 | +If no operands are specified, the I<missing> operand is used. |
| 2933 | + |
| 2934 | +=head1 CONFIGURATION |
| 2935 | + |
| 2936 | +The behaviour of pca can be configured by setting any option either |
| 2937 | +in a configuration file, as an environment variable with the I<PCA_> |
| 2938 | +prefix or on the command line. See OPTIONS for a complete list; only |
| 2939 | +the long names can be used in configuration files and for environment |
| 2940 | +variables. |
| 2941 | + |
| 2942 | +At first, the configuration files are read. pca reads I<pca.conf> |
| 2943 | +in the directory where pca is installed, I<../etc/pca.conf> of the |
| 2944 | +directory where it is installed, I</etc/pca.conf>, I<$HOME/.pca> |
| 2945 | +and I<pca.conf> in the current |
| 2946 | +directory, in this order. In proxy mode the files I<../etc/pca-proxy.conf>, |
| 2947 | +I</etc/pca-proxy.conf> and |
| 2948 | +I<pca-proxy.conf> in the current directory are read, too. |
| 2949 | +Options are set by specifying |
| 2950 | +I<option=value> in the file. Example: To set the path of the wget command, |
| 2951 | +use I<wget=/opt/bin/wget>. To enable debug output, use |
| 2952 | +I<debug=1>. |
| 2953 | + |
| 2954 | +Then, all environment variables matching I<PCA_OPTION> are |
| 2955 | +read. Example: |
| 2956 | +To set the patch download directory, set I<PCA_PATCHDIR> to |
| 2957 | +I</some/dir/>. To set the I<noheader> option, set I<PCA_NOHEADER> |
| 2958 | +to I<1>. |
| 2959 | + |
| 2960 | +At last, the command line options are read. Example: To set the location |
| 2961 | +of the patch xref file, use I<-X /tmp> or I<--xrefdir=/tmp>. |
| 2962 | +To set the option for safe patch installation, use I<-s> or I<--safe>. |
| 2963 | + |
| 2964 | +All boolean options (i.e. those which do not take an argument) can |
| 2965 | +be negated on the command line by specifying I<--no-option> to override |
| 2966 | +settings from configuration files. Version 2.32 or newer of the |
| 2967 | +Getopt::Long module is required. Example: If I<noreboot=1> is set in |
| 2968 | +I<pca.conf> it can be overridden with I<--no-noreboot>. |
| 2969 | + |
| 2970 | +The I<operands> option can only be used in configuration files and as |
| 2971 | +an environment variable. It sets the default OPERANDS. |
| 2972 | + |
| 2973 | +In a configuration file, everything after a I<#> character is |
| 2974 | +regarded as a comment and ignored. |
| 2975 | + |
| 2976 | +=head1 PATCH DOWNLOAD AND INSTALLATION |
| 2977 | + |
| 2978 | +The I<-d> option downloads patches to the current directory, I<-i> |
| 2979 | +downloads and installs them. |
| 2980 | +The download option can be used as a regular user. The external command |
| 2981 | +wget is used for the actual download. If it can't be found in the |
| 2982 | +default paths, set the I<wget> option to contain the path to the |
| 2983 | +wget command. |
| 2984 | +The install option |
| 2985 | +requires pca to be run as root. It uses I<patchadd> to |
| 2986 | +install the patches. |
| 2987 | +Using I<-I> instead of I<-i> |
| 2988 | +pretends to install patches, but does not actually install any patch. |
| 2989 | + |
| 2990 | +The patches are downloaded from Sun's patch download server. |
| 2991 | +To download patches from Sun, a Sun Online Account (SOA) is required. |
| 2992 | +A free SOA will grant access to security and driver patches only. |
| 2993 | +To access all patches, you need to buy a Sun Service Plan and |
| 2994 | +connect it to your SOA. |
| 2995 | +Set the two options I<user> and I<passwd> to contain |
| 2996 | +the SOA user name and password. If I<user> is set, but |
| 2997 | +I<passwd> is not, pca will ask for the password. |
| 2998 | +Alternatively, when run with the I<askauth> option, pca |
| 2999 | +asks for Sun Online Account data interactively. |
| 3000 | + |
| 3001 | +As pca analyzes the information in the cross-reference file to resolve |
| 3002 | +patch dependencies, it lists and installs patches in the correct order. |
| 3003 | + |
| 3004 | +For some patches, a (reconfiguration) reboot is |
| 3005 | +recommended or required after installation. The /reconfigure file |
| 3006 | +is created as needed and a message is shown in the summary. |
| 3007 | +When the I<install> or I<pretend> option |
| 3008 | +is combined with the I<noreboot> option, only patches which do |
| 3009 | +not require a reboot are installed. This information is contained |
| 3010 | +in the patch distribution file. Therefore, even if I<noreboot> |
| 3011 | +is specified, the patches are downloaded anyway; only the installation |
| 3012 | +is skipped. |
| 3013 | + |
| 3014 | +I<patchadd> normally keeps a backup of all files it modifies. |
| 3015 | +Using the I<--nobackup=ID> option with pca instructs |
| 3016 | +I<patchadd> |
| 3017 | +to not keep backup copies of replaced files (see the I<-d> option in |
| 3018 | +patchadd's man page). |
| 3019 | + |
| 3020 | +Sometimes a patch re-delivers |
| 3021 | +and silently overwrites files which have been modified locally. pca |
| 3022 | +tries to overcome this issue with its safe patch installation mode. |
| 3023 | +Before installing a patch, pca checks all files listed in the patch |
| 3024 | +README for local modifications. If any modified file is in danger |
| 3025 | +of being overwritten, a warning is shown and the patch is skipped. |
| 3026 | +Safe mode is off by default, and can be turned on by using I<-s> or |
| 3027 | +I<--safe> in |
| 3028 | +combination with I<-i> (install patches) or I<-I> (pretend to install |
| 3029 | +patches). You must be root to use I<-s>. Running I<pca -s -I> is a |
| 3030 | +safe way of identifying problematic patches without actually installing them. |
| 3031 | + |
| 3032 | +In rare cases, patches modify or replace files without updating the |
| 3033 | +checksum in the package database used by pca. Installing a more recent |
| 3034 | +revision of the same patch will fail although no local modifications |
| 3035 | +have been made to a file. Patch installation can be forced by not |
| 3036 | +using the I<safe> option. |
| 3037 | + |
| 3038 | +Running I<pca -si missingrs> on a regular basis |
| 3039 | +is enough to keep the system at the recommended patch level. |
| 3040 | +This is quite comfortable and works without problems in many cases. |
| 3041 | +As some patches require special handling, |
| 3042 | +it's recommended to read the README of every patch before |
| 3043 | +installation. pca's I<-L> option for HTML output and the |
| 3044 | +I<--readme> option to display patch READMEs are handy for that. |
| 3045 | + |
| 3046 | +Sometimes installing a patch might fail because of inconsistencies |
| 3047 | +in the patchdiag.xref file, the patch README and the |
| 3048 | +information contained inside the patch. Often this gets fixed in a new |
| 3049 | +version of patchdiag.xref or in a new revision of the patch. |
| 3050 | +Either try again a few days later or take a look at the |
| 3051 | +I<Notes> section on the pca web site, where some problematic |
| 3052 | +patches are listed. |
| 3053 | + |
| 3054 | +=head1 LOCAL PATCH SERVER |
| 3055 | + |
| 3056 | +On a local network, it might be useful to have a local patch |
| 3057 | +server. |
| 3058 | +There are two ways to set up a local patch server for pca, using the |
| 3059 | +I<patchurl> and I<xrefurl> options. |
| 3060 | +URLs specified with these options are always accessed first when |
| 3061 | +downloading patches, patch READMEs or patchdiag.xref. |
| 3062 | +Only if a file can't be found |
| 3063 | +there, pca falls back to Sun's patch server. Like this, files |
| 3064 | +are downloaded from Sun's patch server only once when installing |
| 3065 | +patches on multiple machines. |
| 3066 | + |
| 3067 | +Create the local patch repository by copying downloaded patch files |
| 3068 | +(e.g. 123456-78.zip), patch READMEs (e.g. README.123456-78) and/or |
| 3069 | +patchdiag.xref to a |
| 3070 | +directory which is available via NFS or on a local web server. |
| 3071 | +Point pca at it by setting the I<patchurl> and/or I<xrefurl> |
| 3072 | +options to the URL |
| 3073 | +(e.g. file:/patches/ or http://www.my.org/patches/). |
| 3074 | + |
| 3075 | +The more advanced method uses pca to work as a local caching proxy for itself. |
| 3076 | +Create a directory in the document root of the local web server, and |
| 3077 | +link or copy pca there under the name I<pca-proxy.cgi>. Make sure that |
| 3078 | +the directory (or the directories specified with the I<xrefdir> and I<patchdir> |
| 3079 | +options) are owned and writable by the user under which CGI scripts run, |
| 3080 | +as patches, patch READMEs and patchdiag.xref will be stored there. |
| 3081 | +Verify that the |
| 3082 | +web server is configured to run CGI scripts (for apache, check the ExecCGI |
| 3083 | +and AddHandler options in httpd.conf). |
| 3084 | +Create a pca.conf |
| 3085 | +file in the same directory to specify Sun Online Account data. On the client, |
| 3086 | +point |
| 3087 | +pca at the caching proxy by setting the I<patchurl> and I<xrefurl> |
| 3088 | +options to e.g. |
| 3089 | +http://www.my.org/patches/pca-proxy.cgi. |
| 3090 | + |
| 3091 | +In proxy mode, if a patch or |
| 3092 | +patch README exists in the local cache directory, it is delivered |
| 3093 | +immediately. If it doesn't, the file is downloaded from Sun's |
| 3094 | +patch server, put into the cache, and delivered. For patchdiag.xref, |
| 3095 | +I<pca-proxy.cgi> will always make sure that it has a recent |
| 3096 | +version of this file and deliver it from its cache. |
| 3097 | + |
| 3098 | +With a local caching proxy in place, client systems running pca and |
| 3099 | +using this proxy do not need direct access to the Internet at all. |
| 3100 | + |
| 3101 | +Example setup of a local caching proxy on a vanilla Solaris 10 system: |
| 3102 | + |
| 3103 | + # mkdir /var/tmp/pca |
| 3104 | + # chown webservd:webservd /var/tmp/pca |
| 3105 | + |
| 3106 | +This is where patches, READMEs and patchdiag.xref will be stored by |
| 3107 | +the proxy. Now put the CGI script in place and create a configuration |
| 3108 | +file: |
| 3109 | + |
| 3110 | + # cd /var/apache2/cgi-bin |
| 3111 | + # cp /usr/local/bin/pca pca-proxy.cgi |
| 3112 | + # chmod 555 pca-proxy.cgi |
| 3113 | + # cat > /etc/pca-proxy.conf |
| 3114 | + xrefdir=/var/tmp/pca |
| 3115 | + patchdir=/var/tmp/pca |
| 3116 | + user=XXXXXX |
| 3117 | + passwd=YYYYYY |
| 3118 | + ^D |
| 3119 | + # chown webservd:webservd /etc/pca-proxy.conf |
| 3120 | + # chmod 600 /etc/pca-proxy.conf |
| 3121 | + |
| 3122 | +If the apache2 server is not running yet, create I</etc/apache2/httpd.conf> |
| 3123 | +and enable the server with I<svcadm>: |
| 3124 | + |
| 3125 | + # svcadm enable svc:/network/http:apache2 |
| 3126 | + |
| 3127 | +Test the caching proxy on a client: |
| 3128 | + |
| 3129 | + ./pca -X . --xrefurl=http://server.domain/cgi-bin/pca-proxy.cgi |
| 3130 | + --patchurl=http://server.domain/cgi-bin/pca-proxy.cgi -d 126306-01 |
| 3131 | + |
| 3132 | +The patchdiag.xref and 126301-01.zip will be downloaded by the proxy and |
| 3133 | +stored in I</var/tmp/pca/> on the server, and both files will be delivered |
| 3134 | +to the client. If it doesn't work, add I<debug=1> to the pca.conf file |
| 3135 | +and look at /tmp/pca-proxy-debug.txt and /var/apache2/logs/ for details. |
| 3136 | + |
| 3137 | +When downloading large patches through the proxy, you must ensure that |
| 3138 | +the web server does not kill I<pca-proxy.cgi> before it has completed |
| 3139 | +the download from SunSolve. Apache has a I<Timeout> option with a default |
| 3140 | +value of 300 seconds. Raise that to 1800 seconds to avoid problems. |
| 3141 | + |
| 3142 | +For large setups, you can build a cascade of local caching proxies by |
| 3143 | +pointing one proxy at another proxy by setting I<xrefurl> and I<patchurl> |
| 3144 | +to point at the master proxy in the slave proxies' pca.conf. |
| 3145 | + |
| 3146 | +As pca uses the wget command to download patches from the patch server, |
| 3147 | +make sure that any specially required option is set in I</etc/wgetrc> or |
| 3148 | +I<$HOME/.wgetrc>. Example: When running the local patch server on a HTTPS |
| 3149 | +server with a self-signed certificate, I<check-certificate=off> should |
| 3150 | +be specified in I<wgetrc> on the client. |
| 3151 | + |
| 3152 | +=head1 UNBUNDLED PATCHES |
| 3153 | + |
| 3154 | +Usually a patch is related to one or more software packages installed |
| 3155 | +on a system. Apart from that, there are unbundled patches. They |
| 3156 | +provide firmware updates for machines, disks, or tape drives and fixes |
| 3157 | +for software which doesn't come in package format. Currently there is |
| 3158 | +no way to automatically determine if such patches actually apply to a |
| 3159 | +system. |
| 3160 | + |
| 3161 | +The I<unbundled> operand specifies this type of patches. |
| 3162 | +At first, I<pca -l unbundled> will show a long list of patches. |
| 3163 | +To reduce this list |
| 3164 | +to the interesting ones, unnecessary patches can be ignored by using |
| 3165 | +the I<ignore> option in a pca configuration file. |
| 3166 | +For patches you are absolutely not interested in, use an |
| 3167 | +entry like I<ignore=123456> in the configuration file; |
| 3168 | +this patch will never be shown again, even if a newer revision of |
| 3169 | +the patch appears. Patches that are installed in their current revision |
| 3170 | +should be put with this revision into the configuration file |
| 3171 | +(e.g. I<ignore=123456-78>). |
| 3172 | +The patch will show up again when a newer revision is released. |
| 3173 | + |
| 3174 | +Example: Patch 106121-18 contains the most recent PROM firmware for |
| 3175 | +Ultra 5/10 workstations. As it's installed on all systems, I put |
| 3176 | +I<ignore=106121-18> into the configuration file. |
| 3177 | +When a new revision of the patch |
| 3178 | +is released, it will show up in I<pca -l unbundled> again. |
| 3179 | +Patch 118324 is the PROM firmware patch for the Sun Fire V440. As I |
| 3180 | +don't have such a machine, I put I<ignore=118324> into the |
| 3181 | +configuration file to ignore this patch completely. |
| 3182 | + |
| 3183 | +All that pca can do is to notify of new unbundled patches or patch |
| 3184 | +revisions. It's on you to decide whether a patch is needed by checking |
| 3185 | +its README file, and to install it by following the instructions in the |
| 3186 | +README. Unbundled patches cannot be installed by patchadd or pca. |
| 3187 | + |
| 3188 | +=head1 CREATING PATCH REPORTS FOR REMOTE MACHINES |
| 3189 | + |
| 3190 | +pca can create a patch report or download patches for a |
| 3191 | +system which cannot run pca directly, like stripped-down |
| 3192 | +systems without perl or an Internet connection. On such systems, |
| 3193 | +run: |
| 3194 | + |
| 3195 | + uname -a > uname.out |
| 3196 | + showrev -p > showrev.out |
| 3197 | + pkginfo -x > pkginfo.out |
| 3198 | + |
| 3199 | +On systems with a minimal core installation of Solaris, the I<showrev> |
| 3200 | +command might not be available. Use I<patchadd -p E<gt> showrev.out> |
| 3201 | +instead. |
| 3202 | + |
| 3203 | +Copy the resulting I<*.out> files to a system where pca is |
| 3204 | +installed. Use the I<-f DIR> or I<--fromfiles=DIR> option to |
| 3205 | +point pca at the location of the input files. |
| 3206 | +The argument to I<-f> can be a directory |
| 3207 | +or a file name prefix like I<myhost_>. |
| 3208 | +This allows collecting I<*.out> files for multiple systems |
| 3209 | +and telling pca which ones to read. |
| 3210 | + |
| 3211 | +If Sun Explorer is used to collect information about Sun systems, a |
| 3212 | +directory containing Sun Explorer output can be used as the argument |
| 3213 | +to I<-f> as well. |
| 3214 | + |
| 3215 | +Other options can be used in combination |
| 3216 | +with I<-f>. Example: I<pca -f . -d missing> downloads all missing |
| 3217 | +patches for the remote system. |
| 3218 | + |
| 3219 | +=head1 ZONES |
| 3220 | + |
| 3221 | +pca can be run both in the global zone or any non-global zone. Patches |
| 3222 | +installed in the global zone are usually installed in all non-global zones, |
| 3223 | +too. It's recommended to install patches in the global zone first, |
| 3224 | +and then run pca in all non-global zones to check for additionally |
| 3225 | +needed patches. This is necessary if packages have been added to or |
| 3226 | +removed from just the global or any non-global zone. |
| 3227 | + |
| 3228 | +When pca is run with the I<-G> option, this option is handed through |
| 3229 | +to patchadd, which will install patches in the current zone only. See the |
| 3230 | +man page for patchadd for further details. |
| 3231 | + |
| 3232 | +=head1 THREADS |
| 3233 | + |
| 3234 | +If pca is run with the I<--threads=NUM> option, in conjunction with the |
| 3235 | +download I<-d> or install I<-i> options, pca will begin downloading multiple |
| 3236 | +patches in parallel, up to NUM patches at once. Patches will still be |
| 3237 | +installed one at a time, in the appropriate order. |
| 3238 | + |
| 3239 | +The perl version used to run pca must support threading, otherwise requests |
| 3240 | +to use threading will be silently ignored. The /usr/bin/perl which comes with |
| 3241 | +Solaris and perl binaries compiled with the default settings do not |
| 3242 | +support threading. In that case, the output of I<--help> will indicate that |
| 3243 | +threads have been disabled. |
| 3244 | + |
| 3245 | +=head1 UPDATE PCA |
| 3246 | + |
| 3247 | +Changes to the patch infrastructure by Sun and problems with |
| 3248 | +single patches often make updates to pca necessary. To ease that procedure, |
| 3249 | +the I<update=TYPE> option can be used. The default is type I<never> - pca |
| 3250 | +will never |
| 3251 | +check for updates. Use the I<check> type to contact the pca webpage and |
| 3252 | +check for available updates. Using I<now> will not only check, but also |
| 3253 | +download and install the updated version of pca. |
| 3254 | + |
| 3255 | +With I<auto>, pca will check for updates automatically once per day, |
| 3256 | +keeping itself up to date without user intervention. Unlike I<check> |
| 3257 | +and I<now> which are for interactive usage, this type is best used |
| 3258 | +in a configuration file. |
| 3259 | + |
| 3260 | +The default URL to check for updates is |
| 3261 | +http://www.par.univie.ac.at/solaris/pca/stable/ |
| 3262 | +(official release). It can be set with the I<pcaurl=URL> option. |
| 3263 | +Set it to |
| 3264 | +http://www.par.univie.ac.at/solaris/pca/develop/ |
| 3265 | +to check for and update to new development versions of pca. |
| 3266 | +You can set I<pcaurl> to point at a local URL |
| 3267 | +to distribute whatever version in your local network. |
| 3268 | +If set to point at a local caching proxy, the proxy will check |
| 3269 | +for updates automatically, keep a local copy of the pca script |
| 3270 | +in I<patchdir> and deliver it to the client. |
| 3271 | + |
| 3272 | +Set I<update=auto> in the configuration file for pca in proxy mode |
| 3273 | +(I<pca-proxy.cgi>) to make it keep itself up-to-date. |
| 3274 | + |
| 3275 | +=head1 JUMPSTART |
| 3276 | + |
| 3277 | +You can use pca to install patches in the finish script of a jumpstart |
| 3278 | +install server. Perl is included in the OS image which is booted over |
| 3279 | +the network for installation starting with Solaris 8. As the machine |
| 3280 | +will probably not have an Internet connection during installation, you can |
| 3281 | +either pre-download all necessary patches into a directory accessible |
| 3282 | +via NFS, or set up a local caching proxy. If you use any http or ftp |
| 3283 | +url for I<xrefurl> or I<patchurl>, you must put a copy of wget into |
| 3284 | +the directory that contains your finish script and pca, and use the |
| 3285 | +I<wget> option to point pca at it. |
| 3286 | + |
| 3287 | +Set I<patchdir> and I<xrefdir> (unless you use I<nocheckxref>) to /tmp |
| 3288 | +to avoid problems with non-writable directories. As the OS which gets |
| 3289 | +installed during jumpstart is mounted at /a, use the I<root> option to |
| 3290 | +instruct pca to install patches there. |
| 3291 | + |
| 3292 | +=head1 EXAMPLES |
| 3293 | + |
| 3294 | +List all missing patches. This is |
| 3295 | +the same as running pca without any arguments: |
| 3296 | + |
| 3297 | + pca -l missing |
| 3298 | + |
| 3299 | +List all installed security patches: |
| 3300 | + |
| 3301 | + pca -l installeds |
| 3302 | + |
| 3303 | +Display the README for the current revision of patch 116532: |
| 3304 | + |
| 3305 | + pca --readme 116532 |
| 3306 | + |
| 3307 | +Show all installed patches which are marked Bad. You should read the |
| 3308 | +patch README to find out how to handle a specific bad patch: |
| 3309 | + |
| 3310 | + pca -l bad |
| 3311 | + |
| 3312 | +Download multiple explicitly specified patches after asking for |
| 3313 | +Sun Online Account data: |
| 3314 | + |
| 3315 | + pca --askauth -d 121308-02 122032 |
| 3316 | + |
| 3317 | +Download and install all missing patches which do not require to reboot |
| 3318 | +the system in safe mode: |
| 3319 | + |
| 3320 | + pca --noreboot --safe --install |
| 3321 | + |
| 3322 | +Download all missing patches for a remote system. Output from I<uname -a>, |
| 3323 | +I<showrev -p> and I<pkginfo -x> has been saved to /tmp/myhost_uname.out |
| 3324 | +etc. before: |
| 3325 | + |
| 3326 | + pca -f /tmp/myhost_ -d missing |
| 3327 | + |
| 3328 | +Check for a new version of pca and install it: |
| 3329 | + |
| 3330 | + pca --update now |
| 3331 | + |
| 3332 | +A sample configuration file: |
| 3333 | + |
| 3334 | + # Sun Online Account |
| 3335 | + user=myuser |
| 3336 | + passwd=secret |
| 3337 | + # Other |
| 3338 | + patchurl=http://www.my.org/patches/pca-proxy.cgi |
| 3339 | + xrefurl=http://www.my.org/patches/pca-proxy.cgi |
| 3340 | + syslog=user |
| 3341 | + safe=1 |
| 3342 | + |
| 3343 | +=head1 ENVIRONMENT VARIABLES |
| 3344 | + |
| 3345 | +All environment variables with the I<PCA_> prefix are evaluated |
| 3346 | +as options; see CONFIGURATION for details. Furthermore, these environment |
| 3347 | +variables are used by pca: |
| 3348 | + |
| 3349 | +=over 5 |
| 3350 | + |
| 3351 | +=item PAGER |
| 3352 | + |
| 3353 | +Path to the command which is used to display patch README |
| 3354 | +files |
| 3355 | + |
| 3356 | +=back |
| 3357 | + |
| 3358 | +=over 5 |
| 3359 | + |
| 3360 | +=item TMPDIR |
| 3361 | + |
| 3362 | +During patch installation, patches are extracted under this |
| 3363 | +directory |
| 3364 | + |
| 3365 | +=back |
| 3366 | + |
| 3367 | +=head1 AUTHORS |
| 3368 | + |
| 3369 | +Martin Paul E<lt>martin@par.univie.ac.atE<gt> |
| 3370 | + |
| 3371 | +Thanks to everybody who contributed code or provided feedback: |
| 3372 | + |
| 3373 | +Andrew Brooks, Bruce Riddle, Damian Hole, Peter Van Eynde, |
| 3374 | +Richard Whelan, Eugene MacDougal, Peter Schmitz, Fredrik Lundholm, |
| 3375 | +Dan W. Early, Markus Reger, Constantijn Sikkel, Stephen P. Potter, |
| 3376 | +Fletcher Cocquyt, Timothy J. Howard, Thomas Bluhm, Frank Doeschner, |
| 3377 | +Loris Serena, Marion Biallowons, Ricky Chew, Martin R. Korczak, |
| 3378 | +Imad Soltani, Scott Lucas, Anders Grund, Bernd Senf, Chris Zappala, |
| 3379 | +Ashley Krelle, Mike Patnode, Mats Larsson, Thomas Maier-Komor, |
| 3380 | +Willi Burmeister, Stefaan A. Eeckels, Ian Collins, Leptonux, |
| 3381 | +Joseph Millman, Guenter Zaehle, Frank Fejes, Mark Jeffery, |
| 3382 | +Alberto da Silva, Mauricio Tavares, Kurt Rabitsch, Jeff Wieland, |
| 3383 | +Frank Bertels, Steve Meier, Dan Lorenzini, Gerard Henry, Laurent Blume, |
| 3384 | +Sean Berry, George Moberly, Erik Nordenberg, Mark Ashley, Jim Prescott, |
| 3385 | +Christian Pelissier, Hugues Sapin, Colin A. White, Dale T. Long, |
| 3386 | +Christophe Kalt, Bruno Delbono, Nan Liu, Frank Cusack, |
| 3387 | +Marlon Sanchez-Nunez, Jois Diwakar, Toni Viemero, Jens Larsson, |
| 3388 | +Gordon D. Gregory, Luis Catacora, Erik Larson, Tim Longo, Mike Borkowski, |
| 3389 | +Nicolas Goy, William Bonnet, Dave Love, Thomas Brandstetter, Daniel Kunkel, |
| 3390 | +Gregor Longariva, Miroslav Zubcic, Tim Bradshaw, Chris Quenelle, |
| 3391 | +Christopher Odenbach, Andy Fiddaman, Peter Sundstrom, Andreas F. Borchert, |
| 3392 | +Jonah Simandjuntak, Damian Lilley, Chris Ridd, Albert Lee, James Lick, |
| 3393 | +John Douglass, Andres A. Flores Concepcion, Chris Reece, Toni Viemero, |
| 3394 | +Timothy Meader, John D. Groenveld, Ceri Davies, Martin Wismer, |
| 3395 | +Laszlo Kiss, Mike Moya, Leon Koll, Shawn Boots, Mike Wallace, |
| 3396 | +Robert P. McGraw, Peter Arnold, Matt Kolb, Mike Shackelford, John Dzubera, |
| 3397 | +Donald Teed, Asif Iqbal, Stephen Nash, Jason Loretz, Bryan Howard, Roman, |
| 3398 | +Jonathan Hoefker, Daniel Trinkle, Ron Halstead, Rob Fisher, Chris Coffey, |
| 3399 | +Travis Freeland, Hans-Werner Jouy, Gary Mills, Craig Bell, Mick Russom, |
| 3400 | +Brian King, Ashley Rowland, Guillermo Castellini, Bryan D. Moorehead, |
| 3401 | +Mark Scheufele, Corey Becker, David Robson, Kevin Maguire, Mike Wallace, |
| 3402 | +Marcos Della, Frank Sperber, Horst Scheuermann, Adrian Ulrich, Steve Fox, |
| 3403 | +David Collodel, Jeremiah Johnson, Erik Schubert, David Sullivan, |
| 3404 | +Tom Francen, Matthew Scala, Richard Mayebo, Gerald Sinkiewicz, |
| 3405 | +David Montag, Steve Forman, Jeffrey King, Gerry Van Trieste, |
| 3406 | +Chris Denneen, Greg Barry, Paul Armstrong, Andreas Fineske, |
| 3407 | +Eric Kissinger, Torsten Peter, Yevgeniy Averin, Sean Walmsley, |
| 3408 | +Alexander Skwar, Jeffrey King, Jones Olatunji, Richard Skelton, |
| 3409 | +Kjetil Torgrim Homme, Brian McNamara, Gerry Sinkiewicz, Kazuyuki Sato, |
| 3410 | +Mayuresh Kshirsagar, Mauro Mozzarelli, Judy Illeman Gaukel, Petri Kunnari, |
| 3411 | +William Pool, Steven Faulconer, Rono Jacob, Will Green, Martial Rioux, |
| 3412 | +Zafar Pravaiz, Romeo Theriault, Fredrich Maney, Ben Szoko, Pietari Hyvarinen, |
| 3413 | +Roman Pestka, Juergen Mengeling, David S. Bryant, Maciek S., Alexander |
| 3414 | +Sverdlov, David Coronel, David Groce, Jeff Woolsey, Thomas Marshall, |
| 3415 | +Allen Eastwood, Mike Busse, Martin Bellenberg, Dennis Clarke, |
| 3416 | +Dominique Frise, Mark Hopkins, Enda O'Connor, Victor Feng, Peter Englmaier, |
| 3417 | +Paul B. Henson, Gerry Haskins, Jeff A. Earickson, Stuart Anderson, |
| 3418 | +Dagobert Michelsen, Simon Bellwood, Ateeq Altaf, Andrew Berry, Julian Davies, |
| 3419 | +Con Petsoglou, Uwe Wolfram, Micah Cowan, Dan Shaw, Paul Moore, Neal A. Lucier, |
| 3420 | +Eric Bourgi, Sergiusz Pawlowicz, Paul Van Bommel, Matt Banks, Ray Cromwell, |
| 3421 | +Jan Holzhueter, Liam Carey, Alex Docauer, Christopher S. Chan, Philip Kime, |
| 3422 | +Michael Schmarck, Kevin L. Bliss, Thomas Bleek, Albert White, Ron Helzer, |
| 3423 | +Sergei Haramundanis, Steven M. Christensen, Felix Schattschneider, |
| 3424 | +Rajiv G Gunja, Jeremy Simpson, Jesse Caldwell, Amy Rich. |
| 3425 | + |
| 3426 | +=head1 MAILING LISTS |
| 3427 | + |
| 3428 | +Two mailing lists are available: |
| 3429 | + |
| 3430 | +=over 5 |
| 3431 | + |
| 3432 | +=item pca-news |
| 3433 | + |
| 3434 | +This is a one-way list for announcements of new versions and news. |
| 3435 | +To join, send an empty message to E<lt>pca-news-join@lists.univie.ac.atE<gt>. |
| 3436 | + |
| 3437 | +=back |
| 3438 | + |
| 3439 | +=over 5 |
| 3440 | + |
| 3441 | +=item pca |
| 3442 | + |
| 3443 | +This is a discussion and support list. Messages from pca-news will be |
| 3444 | +posted to this list as well. Posting to the list is allowed for |
| 3445 | +non-subscribers. To join, send an empty message to |
| 3446 | +E<lt>pca-join@lists.univie.ac.atE<gt>. To post to the list, send your |
| 3447 | +message to E<lt>pca@lists.univie.ac.atE<gt>. |
| 3448 | + |
| 3449 | +=back |
| 3450 | + |
| 3451 | +=head1 SEE ALSO |
| 3452 | + |
| 3453 | +=over 5 |
| 3454 | + |
| 3455 | +=item pca web site: |
| 3456 | + |
| 3457 | +http://www.par.univie.ac.at/solaris/pca/ |
| 3458 | + |
| 3459 | +=back |
| 3460 | + |
| 3461 | +=head1 CHANGES |
| 3462 | + |
| 3463 | +=head2 Version 20080911-01 |
| 3464 | + |
| 3465 | + * Remove check for patches which are only partly installed |
| 3466 | + |
| 3467 | +=head2 Version 20080909-02 |
| 3468 | + |
| 3469 | + * False positive with partly installed patches: add 120011, 127127 |
| 3470 | + |
| 3471 | +=head2 Version 20080909-01 |
| 3472 | + |
| 3473 | + * Check for patches which are only partly installed |
| 3474 | + * Fix bug with missing patches with multiple versions of the same package |
| 3475 | + * Log failed patch install to syslog |
| 3476 | + * Fix minage option being one day off |
| 3477 | + * Include and use VeriSign certificate for HTTPS downloads from SunSolve |
| 3478 | + * Include and use CyberTrust certificate for HTTPS downloads from pca home |
| 3479 | + * Simplify patch download and pca update code |
| 3480 | + * Simplify patch README download code |
| 3481 | + * Simplify patchdiag.xref download code |
| 3482 | + * Add some debug code |
| 3483 | + * Fix coding error |
| 3484 | + * Code cleanup |
| 3485 | + * Documentation: Better describe what the noheader option does |
| 3486 | + * Fix required patches which were never released: 125486, 125487, 114431 |
| 3487 | + * Fix required patches which were never released: 126677, 126678 |
| 3488 | + * Apply check: modify 119313, 119314 |
| 3489 | + * Update list of contributors |
| 3490 | + |
| 3491 | +Today pca turns 5 years; version 1.0 was published first on 2003/09/09. |
| 3492 | + |
| 3493 | +Thanks to all of you for the large amount of positive feedback I've |
| 3494 | +received during the last years! |
| 3495 | + |
| 3496 | +=head2 Version 20080729-01 |
| 3497 | + |
| 3498 | + * Workaround for 120011/120012 requiring obsolete patches 122660/122661 |
| 3499 | + * Fix a bug when using current version of wget with https |
| 3500 | + * Enhance checks for empty or corrupt patchdiag.xref file |
| 3501 | + * New default URL setting for pcaurl |
| 3502 | + * Apply check: add 121708, 121709, 121710, 125848, 125849, 125850 |
| 3503 | + * Update list of contributors |
| 3504 | + |
| 3505 | +=head2 Version 20080626-01 |
| 3506 | + |
| 3507 | + * New option to list patches with a maximum age (--maxage=DAYS) |
| 3508 | + * Create DIR/reconfigure (not /reconfigure) when using --root=DIR |
| 3509 | + * Don't show ignorable error message from showrev |
| 3510 | + * Fix required patches which were never released: 125077, 125078 |
| 3511 | + * Whitelist: add 120185, 120186 |
| 3512 | + * Whitelist: remove obsolete patches |
| 3513 | + * Apply check: add 137112, 119252, 119253 |
| 3514 | + * Apply check: add 136987, 136986 |
| 3515 | + * Apply check: add 127553, 127554 |
| 3516 | + * Apply check: remove obsolete patches |
| 3517 | + * Update list of contributors |
| 3518 | + |
| 3519 | +=head2 Version 20080519-01 |
| 3520 | + |
| 3521 | + * Fix a bug where pca fails to run when threads option is used |
| 3522 | + * Use locally existing patches in jar format |
| 3523 | + * Read configuration file immediately when cffile option is seen |
| 3524 | + * Enhance performance with hundreds of patch IDs as operands |
| 3525 | + * Fix hanging unzip when no diskspace is left |
| 3526 | + * Show timestamp in debug mode when patchadd is started |
| 3527 | + * Remove duplicate debug message |
| 3528 | + * Documentation: Add note about possible requirement of wgetrc settings |
| 3529 | + * Whitelist: add 137093, 137094 |
| 3530 | + * Apply check: fix 119381 |
| 3531 | + * Apply check: add 125445, 125446 |
| 3532 | + * Cosmetic changes |
| 3533 | + * Update list of contributors |
| 3534 | + |
| 3535 | +=head2 Version 20080507-01 |
| 3536 | + |
| 3537 | + * Add option for concurrent patch downloads (--threads=NUM) |
| 3538 | + * New option to set sunsolve access protocol to HTTPS (--ssprot=PROT) |
| 3539 | + * Ignore HTML tags in patchdiag.xref |
| 3540 | + * Honor wgetproxy option for non-SunSolve URLs as well |
| 3541 | + * Read ../etc/pca-proxy.conf in proxy mode |
| 3542 | + * Fix wget version detection under Red Hat |
| 3543 | + * Make safe option work with ill-formatted README files |
| 3544 | + * Whitelist: add 137274, 137275 |
| 3545 | + * Whitelist: add 127755, 127756, 128307 |
| 3546 | + * Whitelist: add 127127, 127128 |
| 3547 | + * Apply check: add 117429, 118386, 118387, 118388, 118389 |
| 3548 | + * Apply check: add 118828, 118829, 118836, 118837, 118838, 118839, 118840 |
| 3549 | + * Apply check: add 120376, 120377, 120378, 120379, 124689, 124690 |
| 3550 | + * Apply check: add 116338, 116339, 118383, 118384, 125698, 125699 |
| 3551 | + * Apply check: add 111857, 114176 |
| 3552 | + * Apply check: add 119380, 119381 |
| 3553 | + * Update list of contributors |
| 3554 | + |
| 3555 | +=head2 Version 20080311-01 |
| 3556 | + |
| 3557 | + * Try to download patchdiag.xref from alternative sunsolve URL |
| 3558 | + * Add hack to make pca work with wget v1.11 |
| 3559 | + * Add new format specifiers for patch count (%n) and total patches (%t) |
| 3560 | + * Show info header even if no patches are listed |
| 3561 | + * Fix bug with pca not finding its configuration file in some cases |
| 3562 | + * Fix warning about use of uninitialized value |
| 3563 | + * Documentation: Add information about mailing lists |
| 3564 | + * Whitelist: add 127718 |
| 3565 | + * Apply check: add 127719 |
| 3566 | + * Update list of contributors |
| 3567 | + |
| 3568 | +=head2 Version 20080131-01 |
| 3569 | + |
| 3570 | + * New option to display man page (-m/--man) |
| 3571 | + * Make patch utilities patches appear at the top of the list |
| 3572 | + * Create /reconfigure after patch installation if needed |
| 3573 | + * Show correct reboot command in patch installation summary (init 6) |
| 3574 | + * Allow specifying negative patterns with the pattern option |
| 3575 | + * Honore ignore options even if patch IDs are specified explicitely |
| 3576 | + * Make update option work with pcaurl set to a local caching proxy |
| 3577 | + * Make auto update work with pca in proxy mode |
| 3578 | + * Documentation format fixes |
| 3579 | + * Whitelist: add 127718 |
| 3580 | + * Whitelist: remove obsolete patch |
| 3581 | + * Apply check: add 126356, 126357 |
| 3582 | + * Apply check: add 106514, 106515, 108049, 108050, 108879, 108881 |
| 3583 | + * Apply check: add 109120, 109121, 109413, 109414, 117010, 117011 |
| 3584 | + * Apply check: add 117784, 117785, 118195, 118196, 118263, 118264 |
| 3585 | + * Apply check: add 118950, 118951, 123254, 124590 |
| 3586 | + * Apply check: add 124480, 124481, 124482 |
| 3587 | + * Update list of contributors |
| 3588 | + |
| 3589 | +=head2 Version 20080109-01 |
| 3590 | + |
| 3591 | + * Read /etc/pca-proxy.conf and ./pca-proxy.conf in proxy mode |
| 3592 | + * New option to specify additional configuration files (--cffile=FILE) |
| 3593 | + * Allow negating boolean options on the command line with --no-option |
| 3594 | + * Documentation: Add information about the Timeout option in Apache |
| 3595 | + * Whitelist: add 125082, 125890, 128624 |
| 3596 | + * Whitelist: remove obsolete patch |
| 3597 | + * Apply check: add SAM-FS and QFS patches |
| 3598 | + |
| 3599 | +Use /etc/pca-proxy.conf or pca-proxy.conf in the same directory as |
| 3600 | +the CGI script from now on. For downward compatibility pca-proxy.cgi |
| 3601 | +will still read pca.conf in the standard locations, but this is |
| 3602 | +deprecated. |
| 3603 | + |
| 3604 | +=head2 Version 20071214-01 |
| 3605 | + |
| 3606 | + * Enhance check for circular patch dependencies |
| 3607 | + * Enhance error handling |
| 3608 | + * Update list of contributors |
| 3609 | + * Whitelist: add 118717, 127111, 127112 |
| 3610 | + |
| 3611 | +=head2 Version 20071115-01 |
| 3612 | + |
| 3613 | + * Streamline patch downloads from local caching proxy |
| 3614 | + * More verbose output during downloads and patch installation |
| 3615 | + * Complete code redesign of all download functions |
| 3616 | + * Try to download patchdiag.xref from sunsolve without SOA data |
| 3617 | + * Always keep backup copy of patchdiag.xref before trying download |
| 3618 | + * Use downloaded copy of patchdiag.xref if date is equal to backup copy |
| 3619 | + * Always check if downloaded copy of xref file is newer than local copy |
| 3620 | + * Restore backup copy of patchdiag.xref if pca is interrupted |
| 3621 | + * Correctly handle SOA password with # sign in configuration file |
| 3622 | + * Add trailing slash to download URL if missing |
| 3623 | + * Show wget version in debug output |
| 3624 | + * Fix bug when installing patch using previously unpacked patch directory |
| 3625 | + * Change implementation of file type recognition |
| 3626 | + * Fix perl warning |
| 3627 | + * Update list of contributors |
| 3628 | + |
| 3629 | +Attention: There has been a change in the protocol used to download |
| 3630 | +patches from the local caching proxy. Make sure to update both pca |
| 3631 | +and pca-proxy.cgi. |
| 3632 | + |
| 3633 | +The output format of pca has been changed to give more detailed information |
| 3634 | +about download sources and patch installation. |
| 3635 | + |
| 3636 | +SunSolve has changed in a way that download of the patchdiag.xref file |
| 3637 | +is possible without a Sun Online Account again. pca now tries both with |
| 3638 | +and without SOA. |
| 3639 | + |
| 3640 | +=head2 Version 20071023-01 |
| 3641 | + |
| 3642 | + * Change nobackup option to accept a patch ID or "all" as argument |
| 3643 | + * Preserve local copy of patchdiag.xref if sunsolve copy is older |
| 3644 | + * New option to set sunsolve hostname or IP address (--sshost=HOST) |
| 3645 | + * Honor setting of nocheckxref option in proxy mode |
| 3646 | + * Detect absolute path names for xrefdir/patchdir under Windows |
| 3647 | + * Use "--execute cache=off" instead of "--cache=off" with nocache |
| 3648 | + * Show patchadd command in debug output |
| 3649 | + * Fix debug message shown when safe option is used |
| 3650 | + * Remove temporary entry for 126509 which was missing from xref |
| 3651 | + * Apply check: add 123202 |
| 3652 | + * Apply check: add 123827, 123828, 123829 |
| 3653 | + * Apply check: add 125760, 125761, 125762 |
| 3654 | + |
| 3655 | +The nobackup option requires an argument now. Instead of --nobackup |
| 3656 | +use --nobackup=all, or specify selected (e.g. large) patches in |
| 3657 | +multiple nobackup options. |
| 3658 | + |
| 3659 | +SunSolve is sometimes delivering out-of-date versions of the |
| 3660 | +patchdiag.xref file. pca now checks the date in the header and |
| 3661 | +will not overwrite a more recent local copy with an outdated file |
| 3662 | +from SunSolve. |
| 3663 | + |
| 3664 | +=head2 Version 20071011-02 |
| 3665 | + |
| 3666 | + * A Sun Online Account is needed to access patchdiag.xref |
| 3667 | + * Modify askauth to ask for authentication data when needed |
| 3668 | + * Use same URL for patch README in HTML output with and without SOA |
| 3669 | + * Fix bug with update showing old list of changes |
| 3670 | + * Fix typo in reconfiguration message |
| 3671 | + * Documentation: Clarify information about ignore option |
| 3672 | + * Whitelist: add 121429, 119757, 119758, 125367, 125368 |
| 3673 | + * Whitelist: modify 121428 |
| 3674 | + |
| 3675 | +With a recent change to SunSolve, a Sun Online Account is now required |
| 3676 | +to allow pca downloading the patchdiag.xref file. The askauth option |
| 3677 | +has been modified to ask for the Sun Online Account in that case, too. |
| 3678 | + |
| 3679 | +=head2 Version 20071005-03 |
| 3680 | + |
| 3681 | + * Add documentation about using pca in a jumpstart finish script |
| 3682 | + * Whitelist: modify 120011 |
| 3683 | + * Fix small bug with installing Sun Studio 11 patches on Solaris 10 |
| 3684 | + |
| 3685 | +=head2 Version 20071002-01 |
| 3686 | + |
| 3687 | + * New option to allow pca to update itself (--update=TYPE) |
| 3688 | + * Code cleanup and performance enhancements |
| 3689 | + * Deliver files in proxy mode directly without HTTP redirect |
| 3690 | + * Write debug output to file in proxy mode |
| 3691 | + * Fix a problem with timelocal when running pca under Windows |
| 3692 | + * Fix obscure bug with --safe option and pathnames with commas |
| 3693 | + * Add option to stop after a specified patch ID (--stop=ID) |
| 3694 | + * Allow patch proxy to download files from another patch proxy |
| 3695 | + * Revert to old mechanism of specifying user and password with wget |
| 3696 | + * Include documentation in pca |
| 3697 | + * Handle relative path names in xrefdir correctly |
| 3698 | + * Whitelist: add 120011, 125369, 120012, 125216, 125370 |
| 3699 | + * Whitelist: modify 118833 |
| 3700 | + * Whitelist: remove obsolete patches |
| 3701 | + * Apply check: add 125950, 125951, 125952, 125953 |
| 3702 | + * Apply check: add 121430, 121431, 121428 |
| 3703 | + * Apply check: add 125276, 125277, 125278 |
| 3704 | + * Apply check: remove obsolete patches |
| 3705 | + |
| 3706 | +There is a new version scheme, consisting of the date in ISO format plus a |
| 3707 | +serial number. The same scheme is used for official and development releases. |
| 3708 | +A new option has been added (update=TYPE) which allows pca to check for and |
| 3709 | +install new versions of itself. See UPDATE PCA in the documentation. The |
| 3710 | +documentation is now included in POD format in pca. Use |
| 3711 | +I</usr/perl5/bin/perldoc pca> to view it. |
| 3712 | + |
| 3713 | +There are some enhancements to pca in proxy mode. You can setup a cascade |
| 3714 | +of local proxies by pointing one proxy at another. The xrefdir and patchdir |
| 3715 | +are honored now in proxy mode, so you can keep the cache directory out of |
| 3716 | +the document root of your web server and use an existing cgi-bin directory. |
| 3717 | +Debugging a proxy is simplified; when the debug option is set, debug output |
| 3718 | +will be written to a file. |
| 3719 | + |
| 3720 | +=cut |
| 3721 | + |
| 3722 | +# O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2 |
| 3723 | +-----BEGIN CERTIFICATE----- |
| 3724 | +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ |
| 3725 | +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh |
| 3726 | +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy |
| 3727 | +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp |
| 3728 | +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X |
| 3729 | +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw |
| 3730 | +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg |
| 3731 | +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo |
| 3732 | +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 |
| 3733 | +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB |
| 3734 | +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 |
| 3735 | +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 |
| 3736 | +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID |
| 3737 | +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk |
| 3738 | +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i |
| 3739 | +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY |
| 3740 | +oJ2daZH9 |
| 3741 | +-----END CERTIFICATE----- |
| 3742 | + |
| 3743 | +# O=GTE Corporation, CN=GTE CyberTrust Global Root |
| 3744 | +-----BEGIN CERTIFICATE----- |
| 3745 | +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD |
| 3746 | +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv |
| 3747 | +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv |
| 3748 | +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV |
| 3749 | +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU |
| 3750 | +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds |
| 3751 | +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH |
| 3752 | +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS |
| 3753 | +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 |
| 3754 | +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r |
| 3755 | +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 |
| 3756 | +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P |
| 3757 | +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ |
| 3758 | +-----END CERTIFICATE----- |