A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 #!/bin/bash 2 ################################################### 3 # fou4s - Fast Online Update for SuSE 4 # 5 # Copyright (C) 2002-2009 Markus Gaugusch <fou4s@gaugusch.at> 6 # Many improvements by Lars Ellenberg <l.g.e@web.de> 7 # 8 # See man page fou4s(1) for more information or look at http://fou4s.gaugusch.at 9 # 10 # SVN info: 11 # $Author: markus $ 12 # $Date: 2012-03-22 07:38:26 +0100 (Don, 22 Mär 2012) $ 13 # $Rev: 224 $ 14 # 15 # Optimized for tabstop length 3 and terminal width ~160 chars 16 # 17 # This program is free software; you can redistribute it and/or 18 # modify it under the terms of the GNU General Public License 19 # as published by the Free Software Foundation; either version 2 20 # of the License, or (at your option) any later version. 21 # 22 # This program is distributed in the hope that it will be useful, 23 # but WITHOUT ANY WARRANTY; without even the implied warranty of 24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 # GNU General Public License for more details. 26 # 27 # You should have received a copy of the GNU General Public License 28 # along with this program; if not, write to the Free Software 29 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 30 # 31 ################################################## 32 33 FOUVERSION=0.16.0 34 [[ $FOUVERSION == *beta* ]] && BETA=beta- # used for self-update of fou4s 35 [[ $FOUVERSION == *rc* ]] && BETA=beta- # used for self-update of fou4s 36 # probably need extended globbing for pattern matching 37 # available at least since suse 6.1 (but maybe not for people running fou4s 38 # in "server" mode on other unices) 39 shopt -s extglob \ 40 || { 41 echo "Need extended globbing or some features will fail!" 42 echo "Please update to a newer version of bash." 43 exit 255 44 } 45 unset LANG # to get sane error messages (necessary for parsing) 46 unset LC_CTYPE 47 HOSTNAME=`hostname` # for tcsh, which sets $HOSTNAME to fqdn 48 WHOAMI=$0 49 [[ $WHOAMI != /* ]] && WHOAMI="$PWD/${0#./}" 50 DIRNAME=${WHOAMI%/*} 51 BASENAME=${WHOAMI##*/} 52 53 54 if [[ $1 == --rightsok ]] || [[ $1 == --ri* ]] ; then 55 shift # remove the rightsok parameter from parameter list 56 elif [[ -x `type -p sg` ]] ; then # only if sg exists - it is missing on some SuSE versions 57 groups=`grep ^fou4s: /etc/group` 58 # If root or members of group fou4s call fou4s, set group fou4s and 59 # make all files group writeable 60 if [[ $EUID -eq 0 && -n $groups || $groups != *: ]] ; then 61 umask g+rwx 62 sg fou4s -c "$0 --rightsok $*" && exit 63 [[ $? -eq 1 ]] && echo "You don't have group fou4s in your system, please run 'groupadd fou4s'!" || exit $? 64 fi 65 fi 66 67 ################################ getSuSEVersion 68 # get version of the running suse product. Used to get the right 69 # patches from ftp server. 70 # Modifies: SUSEVERSION, ARCH, SUSEPRODUCT, NODOTSUSEVERSION 71 # UsedBy: main 72 function getSuSEVersion() 73 { 74 local ver dir i 75 dir=`dirname $0` 76 [[ -O $dir/SuSE-release && -x $dir/SuSE-release ]] && ver=(`$dir/SuSE-release v1.2`) || \ 77 for i in /usr/bin /usr/local/bin ; do 78 [[ -x $i/SuSE-release ]] && ver=(`$i/SuSE-release v1.2`) && break 79 done 80 SUSEVERSION=${ver[1]} 81 NODOTSUSEVERSION=${ver[2]} 82 ARCH=${ver[3]} 83 SUSEPRODUCT=${ver[4]//\"} # vim syntax helper: " 84 KERNELVER=${ver[5]} 85 MACHINEARCH=${ver[6]} 86 VALIDARCHS=${ver[7]//+/ } 87 } # getSuSEVersion 88 89 90 # --------------------------- 91 # global variable definitions 92 # --------------------------- 93 getSuSEVersion # needed for some variables 94 ACCEPTPREINSTALLINFO=0 # Don't require interactive mode for preinstall info 95 ALLCOUNT=0 # current index in list of all packages 96 ALLPKGDESCFILES= # for package description cache 97 AUTOLIST= # List of packages to install automatically 98 AUTOMODE=0 # Automatic installation of selected packages 99 BASEDIR=$PWD # current directory, needed to access relative paths (rpmdir,..) 100 BENCHMARK=0 # do benchmark and use fastest server 101 CACHEDIR=/var/cache/fou4s # default cache root directory 102 CHECKDELETED=1 # check for deleted files that are still accessed after update 103 CHECKONLYDELETED=0 # check for deleted files and exit 104 CHECKFOU=1 # check for update of fou4s 105 CHECKONLY=0 # only compare patch descriptions with RPM db 106 CLEANCACHE=0 # clean update description cache (see --cleancache) 107 COLOR=1 # use colored output 108 COLUMNS=80 # width of screen output (default) 109 COMMONFUNCS=0 # for announcement2pkgdesc to include fou4s functions 110 COMPATIBLE=1 # be as compatible as possible to YOU 111 CONFIGFILE=None # default config file (information text only, in this case) 112 CONFIGFILES="/etc/fou4s.conf $HOME/.fou4s ./.fou4s" # config files, the last one has highest priority 113 CRONINST=0 # install cronjob 114 CRONSERVER=0 # install cronjob for server (24h connected) 115 CRONWORKSTATION=0 # install cronjob for workstation 116 DAYSOLDER=0 # only show packages older than n days 117 DLPATH=$CACHEDIR/packages # default path for downloaded RPMs 118 DOINSTALL=0 # perform installation/download 119 DORECODE=0 # translate from UTF8 to ISO8859-15 120 DOWNLOAD=0 # attempt to download files 121 EXCLUDELIST= # skip packages of this series (blank seperated) 122 EXPORTFILE= # filename for export function 123 EXPORT=0 # export files to install/download on/for another host 124 FAILCOUNT=0 # number of failed updates (dependency problems, etc.) 125 FIXPERMS=0 # Fix permissions of package descr. file on SuSE 8.1 for nonroot 126 FORCEDARCH= # arch given on commandline 127 FORCEINSTALL=0 # force installation of current patch set 128 FOU4SKEY=AFB66D7C # fou4s build key id 129 FOUNDFILE= # return variable for fileExists() 130 GENERATED=1 # check for generated package descriptions 131 GET81PACKAGEDESCRIPTIONS=0 # get package description file for 8.1 from ftp 132 GETALL=0 # download all packages 133 GETALLNEW=0 # download only packages that are not installed or newer 134 GETSOURCE=0 # download src.rpm only 135 GLOBALRPMOPTS= # global rpm installation options (to be set later) 136 GLOBALWGETOPTS='--retr-symlinks -np -nd -e robots=off --reject="=D,=A" --passive-ftp --timestamping -t3' 137 GLOBALWGETOPTS="$GLOBALWGETOPTS --user-agent=fou4s-$FOUVERSION" 138 GLOBALCURLOPTS="-A fou4s-$FOUVERSION --progress-bar -C - -L" 139 HTTPPASSWD= # For SuSE business products 140 HTTPUSER= # For SuSE business products 141 HOSTEXEC= # used to execute commands at remote hosts 142 IGNORELIST= # packages that shouldn't be installed 143 IMPORT=0 # import files to install/download from/for another host 144 IMPORTFILE= # filename for import function 145 INSTMODE=1 # 0=Every package alone, 1=each patchfile grouped, 2=All at end 146 INTERACTIVE=0 # interactive mode 147 KERNELPKG= # name of package containing kernel 148 KERNELCHECK=1 # special handling for linux kernel updates 149 KERNELBACKUP=1 # create backup when doing a kernel update 150 LANGUAGE=english # for info from update descriptions 151 LIMIT=0 # no bandwith limits by default 152 LISTAVAILRPMS=0 # list available RPM files 153 LOGFILE=/var/log/fou4s.log # logfile that contains all installed updates 154 LOGLEVEL=1 # Loglevel for logfile, 0=lowest, 3=full debug 155 NORESUME=0 # Only work with complete files (no continued download) 156 OFFLINE=0 # Connect to remote host when checking for updates 157 ONLYINSTALLEDUSERRPMS=0 # only process installed user specified rpms 158 PACKAGES81= 159 PATCHDIR=patches # repodata for 10.1 160 PATCHRPMS=1 # use patch rpm's on SuSE 8.1 if possible 161 POSTINSTLIST= # List of patch descriptions containing postinstall info 162 POSTINFO=0 # show postinstall information (later overwritten for each pkg) 163 PROXYDIGEST=0 # use digest auth with proxy (enforces curl) 164 PROXYPASS= # http proxy password 165 PROXYUSER= # http proxy username 166 QUIET=0 # quiet mode (for cron jobs) 167 REMARKLIST= # packages that shouldn't be installed, but remarked if 168 REMOVE=1 # remove packages after (successful) install 169 RPMINSTLIST= # global RPM installation list 170 RPMEXPORTLIST= # list of RPM's to be exported to other host 171 RPMCACHEVER=2.1 # version of the RPM cache file 172 RWIDTH=22 # width of rpm name field in output 173 RSYNCSERVER=rsync://ftp.gwdg.de/SuSE/ftp.suse.com/suse/$ARCH #default for gpd.sh 174 RSYNCOPTS="-t --partial" # global rsync options: timestamps 175 SAFEMODE=0 # don't check for package signatures and don't run insttriggers 176 SECURITY=0 # only install security updates 177 SERVERLIST= # download server 178 SKIPGPG=0 # skip GPG verification 179 SKIPOPTIONAL=0 # skip optional packages 180 SRCRPMS= # list of packages that are downloaded as src.rpm 181 SUSECONFIG=1 # run SuSEconfig after update 182 TESTMODE=0 # run in testing mode 183 THREADS=1 # run in multi-threaded mode 184 UPDATEPACKAGELIST=0 # update list of available updates 185 UPDATESERVERLIST=0 # update list of ftp servers 186 UPDATESUSESERVERS=0 # update /etc/suseservers 187 USEBUILDTIME=0 # don't compare versions, but the build time of the packages 188 USECACHE=2 # cache for package descriptions 189 USECURL=0 # use curl instead of wget 190 USEDELTARPMS=1 # support for delta rpms 191 USEDIR=0 # use "directory" or "directory.1" files ... 192 USEFULLPATH=1 # support for structured (a1/aaa_base.rpm) download dir 193 USEPROGRESS=1 # default, will be reset later after option parsing 194 USERRPMS= # user requested RPM file(s) 195 USERSYNCPROXY=1 # use --proxy value as rsync proxy 196 VCMP_OK=0 # try to use zypper vcmp if our vcmp fails 197 VERBOSE=0 # more (debug) output 198 VERSIONOVERRIDE=0 # this is set to 1, if user overrides detected values 199 XMLP= # path to xmlp awk script (filled later) 200 LASTANSWER=n # last answer for user input 201 INVERSE=0 # inverse coloring (for white background terminals) 202 BRIGHT=1 # bright colors 203 COUNTER=(0 0 0 0 0 0 0 0 0) # array for counters 204 SIZES=(0 0 0 0 0 0 0 0 0) # array for sizes 205 HDSIZES=(0 0 0 0 0 0 0 0) # size on hdd 206 DLSIZES=(0 0 0 0 0 0 0 0) # size of missing data 207 _ZERO=0 # packages with zero size 208 _SECURITY=1 # -"- for security packages 209 _RECOMMENDED=2 # ... recommended packages 210 _OPTIONAL=3 # optional packages 211 _YAST=4 # yast packages 212 _GENERATED=5 # generated packages 213 _SCRIPT=6 # scripts 214 _ALL=7 # packages that need to be updated 215 _INST=8 # installed packages 216 217 218 # Global variable RETVAL for non $? success/failure return values 219 # array variable, you could return more than one value 220 # if refered without index, you get index 0, the default. 221 RETVAL=() 222 223 224 ################################ 225 ################################ Functions 226 ################################ 227 228 229 ################################ myEcho 230 # write message, but only if debug level is right 231 # parameters: 232 # $1 verbosity level [0-4] 233 # $2 Text to write to stdout if level is ok 234 function myEcho() 235 { 236 [[ $VERBOSE -lt $1 ]] || echo -e "${@: 2}" 237 } # myEcho 238 239 ################################ myWarn 240 # print warning message, but only if debug level is right 241 # parameters: 242 # $1 verbosity level [0-4] 243 # $2 Text to write to stdout if level is ok 244 function myWarn() 245 { 246 echo -en ${COL_YELLOW} 247 myEcho "$@" 248 echo -en ${COL_NORM} 249 } # myWarn 250 251 252 ################################ myError 253 # print error message, but only if debug level is right 254 # parameters: 255 # $1 verbosity level [0-4] 256 # $2 Text to write to stdout if level is ok 257 function myError() 258 { 259 echo -en ${COL_RED} 260 myEcho "$@" 261 echo -en ${COL_NORM} 262 } # myError 263 264 265 ################################ myNote 266 # print notification message, but only if debug level is right 267 # parameters: 268 # $1 verbosity level [0-4] 269 # $2 Text to write to stdout if level is ok 270 function myNote() 271 { 272 echo -en ${COL_CYAN} 273 myEcho "$@" 274 echo -en ${COL_NORM} 275 } # myNote 276 277 278 ################################ myRead 279 # Like bash "read", but simplifies answer (Y/Yes->y, ...) 280 # parameters are passed to bash read command, but prompt 281 # must always be given. The answer is returned in $answer 282 function myRead() 283 { 284 eval read -p '"$*"' answer 285 case $answer in 286 Y|yes|Yes|YES) eval answer=y ;; 287 N|no|No|NO) eval answer=n ;; 288 S|skip) eval answer=n ;; 289 esac 290 } 291 292 293 ################################ logWrite 294 # Appends some text to $LOGFILE with timestamp 295 # Parameters: 296 # $1: loglevel (like $VERBOSE) 297 # rest: text 298 function logWrite() 299 { 300 [[ $LOGLEVEL -lt $1 ]] && return 301 shift 302 local time=`date "+%Y-%m-%d %H:%M:%S"` 303 echo $time $* >> $LOGFILE 304 } # logWrite 305 306 307 ################################ checkLanguage 308 # checks if the given text is nonzero and changes language to english if it is 309 function checkLanguage() 310 { 311 [[ -z $1 ]] && return 1 312 return 0 313 } 314 315 ################################ showUsageShort 316 # short overview about fou4s options 317 # UsedBy: checkParameters 318 function showUsageShort() 319 { 320 cat << _EOF 321 fou4s v$FOUVERSION (c) 2002-2009 Markus Gaugusch <fou4s@gaugusch.at> 322 usage: fou4s -u [-bqv] [--checkfou4s] [--proxyuser] 323 [--proxypasswd] 324 fou4s -e [--all] [-bdosv] [--proxyuser] [--proxypasswd] 325 fou4s --auto [-nosv] 326 fou4s -i [-abcdgnorsv] [-f file] [--interactive] [--nodeps] 327 [--proxyuser] [--proxypasswd] 328 fou4s -l [-os] 329 fou4s --server [-vw] [--proxyuser] [--proxypasswd] 330 fou4s --checkdeleted 331 fou4s --fixperm 332 Type fou4s --help for more information. 333 See the manual page fou4s(1) for detailed help. 334 _EOF 335 exit 0 336 } # showUsageShort 337 338 339 ################################ showUsage 340 # show long usage information and exit 341 # UsedBy: checkParameters 342 function showUsage() 343 { 344 cat << _EOF 345 fou4s v$FOUVERSION (c) 2002-2009 Markus Gaugusch <fou4s@gaugusch.at> 346 usage: fou4s [task] [options] 347 task: 348 -u, --update Get new package list from FTP server and exit 349 -i, --install Compare package list with RPM db and get/install packages 350 --all Process all available packages, no matter if they are needed 351 --allnew Process packages that are newer or not installed yet 352 --auto Works like -ued, plus auto installation of specific packages 353 -e, --evaluate Evaluate, if new updates should be installed (no dl/install) 354 -l, --list List available RPMs (for use with -f) 355 --server Select ftp server to use (interactive) 356 --checkdeleted Check for deleted files that are still in use and exit 357 --fixperm Fix package descr. file read permissions on 8.1 for group fou4s 358 options: 359 -a Install every package immediately after downloading (see --end) 360 --arch Override architecture autodetect (get packages for other arch) 361 -b, --benchmark Do benchmark (fou4s-benchmark) and use fastest server 362 --buildtime Compare buildtime of packages instead of version number 363 -c Do not run SuSEconfig after update (requires -i) 364 --config cfgfile Use "cfgfile" as configuration file. Must be the first option 365 --checkfou4s Check for an updated version of fou4s (requires -u) 366 -d Check packages and download RPMs (no installation) 367 --end Install all updates at the end, not when listing them (see -a) 368 --exclude x Don't check patch description 'x' or series 'x' (wildcards ok) 369 -f custom.rpm Try to process the given file(s). -l shows available RPMs 370 --force Force RPM updates. (DANGEROUS!!) 371 -g, --nogpg Skip GPG signature verification (beware!) 372 -h Short help 373 --help Show this help screen 374 --interactive Interactive mode (ask before downloading/installing a package) 375 --inversecolor To see color on black-on-white terminals 376 --language x Use the given language for descriptions (e.g. german or french) 377 --limit-rate x Limit downloads to x kb/sec 378 -n, --nodownload Do not attempt to download RPM files 379 --nocache Do not use the update description cache 380 --nocheckdeleted Do not check for deleted files still in use at end of run 381 --nocolor Do not use colored output 382 --nocompatible Don't try to be compatible to YOU. See man page fou4s(1) 383 --nodeps Don't make RPM dependency checks (DANGEROUS!) 384 --nodeltarpms Don't use delta RPMs if possible (only SuSE 9.2+) 385 --nopatchrpms Don't use patch RPMs if possible 386 --nogenerated Don't use generated package descriptions 387 --noproxy Don't use http_proxy/ftp_proxy (from environment var.) 388 -o Skip optional packages (process everything else) 389 --older-than x Only show packages older than x days 390 --only Only process specified RPMs, see -f 391 --product x Update for SuSE Business product (e.g. eMail-Server) 392 --proxy x Use "x" as proxy server. Format is http://host:port/ 393 --proxydigest Use digest authentication with proxy (curl only!) 394 --proxyuser user Use username "user" for HTTP proxy (if required) 395 --proxypasswd pw Use password "pw" for HTTP proxy (if required) 396 -q, --quiet Quiet mode (for cron-jobs) 397 -r, --remove Remove downloaded packages after successful update 398 -s, --security Only process security updates (nothing else) 399 --safemode Don't check signatures and disable install triggers (faster) 400 --src rpm1,... Download source RPM for given packages 401 --suseuser x Username for http auth (for business products) 402 --susepasswd x Password for http auth (for business products) 403 --suseversion Override version autodetect (get packages for other SuSE rel.) 404 --usecurl Use curl instead of wget 405 --usedir Use directory.X files from YOU (see fou4s(1)) 406 -v, --verbose Verbose mode (twice for even more verbosity) 407 --version Show version information 408 -w Update /etc/suseservers (only valid with --server) 409 _EOF 410 # --noresume Don't resume downloads (delete old files first) 411 exit 0 412 } # showUsage 413 414 415 ################################ checkParameters 416 # processes fou4s command line parameters 417 # UsedBy: main 418 # Modifies: a lot 419 # parameters: 420 # $*: command line parameters to fou4s 421 function checkParameters() 422 { 423 while [[ $# -gt 0 ]] ; do # parameter checking 424 case "$1" in 425 -a) 426 INSTMODE=0 427 shift ;; 428 --acceptpreinstallinfo) 429 ACCEPTPREINSTALLINFO=1 430 shift ;; 431 --all) 432 PATCHRPMS=0 # don't use patch rpms when getting all packages 433 GETALL=1 434 [[ $USECACHE -ge 2 ]] && USECACHE=1 # only use level-1 cache (level-2 is invalid) 435 shift ;; 436 --allnew) 437 PATCHRPMS=0 # don't use patch rpms when getting all packages 438 GETALL=1 439 GETALLNEW=1 440 [[ $USECACHE -ge 2 ]] && USECACHE=1 # only use level-1 cache (level-2 is invalid) 441 shift ;; 442 --arch) 443 ARCH=$2 444 MACHINEARCH=$2 445 FORCEDARCH=$2 446 shift 2 ;; 447 --auto) 448 DOINSTALL=1 # installs only auto mode packages 449 QUIET=1 # quiet is for -u (not used anywhere else) 450 VERBOSE=1 # verbose is for -e (show update descriptions) 451 AUTOMODE=1 UPDATEPACKAGELIST=1 DOWNLOAD=1 452 shift ;; 453 -b|--benchmark) 454 BENCHMARK=1 455 shift ;; 456 --buildtime) 457 USEBUILDTIME=1 458 shift ;; 459 -c) 460 SUSECONFIG=0 461 shift ;; 462 --checkdeleted) 463 CHECKONLYDELETED=1 464 shift ;; 465 --checkfou4s) 466 CHECKFOU=1 467 shift ;; 468 --cleancache) 469 CLEANCACHE=1 470 shift ;; 471 --commonfuncs) 472 COMMONFUNCS=1 473 shift ;; 474 --cronserver) 475 CRONINST=1 476 CRONSERVER=1 477 shift ;; 478 --cronworkstation) 479 CRONINST=1 480 CRONWORKSTATION=1 481 shift ;; 482 -d) 483 DOWNLOAD=1 484 shift ;; 485 -e|--evaluate) 486 CHECKONLY=1 487 shift ;; 488 --end) 489 INSTMODE=2 490 shift ;; 491 --exclude) 492 EXCLUDELIST="$EXCLUDELIST $2" # multiple --exclude's should be legal 493 shift 2 ;; 494 --exportx) # the appended x is a hack for broken vim colors in getopt 495 EXPORTFILE=$2 496 EXPORT=1 497 DOINSTALL=1 # is skipped later, but needed for storing in tar file 498 DOWNLOAD=1 499 SUSECONFIG=0 500 USEDELTARPMS=0 # delta rpms don't work for remote machines 501 shift 2 ;; 502 -f) 503 USERRPMS="$USERRPMS $2" 504 shift 2 ;; 505 --fixperm) 506 FIXPERMS=1 507 shift ;; 508 --force) 509 GLOBALRPMOPTS="$GLOBALRPMOPTS --force" 510 shift ;; 511 -g|--nogpg) 512 SKIPGPG=1 513 shift ;; 514 --getpackagedescriptions) 515 GET81PACKAGEDESCRIPTIONS=1 516 shift ;; 517 -h) 518 showUsageShort ;; # no shift necessary, function makes exit 519 --help) 520 showUsage ;; # no shift necessary, function makes exit 521 --host) 522 HOSTNAME=${2##*@} 523 HOSTEXEC="ssh $2" 524 CHECKDELETED=0 # cannot check for deleted files on remote servers! 525 USEDELTARPMS=0 # delta rpms don't work for remote machines 526 shift 2 ;; 527 -i|--install|--upgrade) 528 DOINSTALL=1 DOWNLOAD=1 CHECKONLY=0 529 shift ;; 530 --import) 531 IMPORTFILE=$2 532 IMPORT=1 533 shift 2 ;; 534 --interactive) 535 INTERACTIVE=1 536 shift ;; 537 --inversecolor) 538 INVERSE=1 539 shift ;; 540 -l|--list) 541 LISTAVAILRPMS=1 542 USECACHE=1 543 USEPROGRESS=0 544 shift ;; 545 --language) 546 LANGUAGE=$2 547 shift 2 ;; 548 --limit-rate) 549 LIMIT=$2 550 shift 2 ;; 551 -n|--nodownload) 552 DOWNLOAD=0 553 [[ $AUTOMODE -eq 0 ]] && UPDATEPACKAGELIST=0 554 shift ;; 555 --nocache) 556 USECACHE=$((USECACHE-1)) 557 [[ $USECACHE -lt 0 ]] && USECACHE=0 558 shift ;; 559 --nocheckdeleted) 560 CHECKDELETED=0 561 shift ;; 562 --nocolor) 563 COLOR=0 564 shift ;; 565 --nocompatible) 566 COMPATIBLE=0 567 shift ;; 568 --nodeps) 569 GLOBALRPMOPTS="$GLOBALRPMOPTS --nodeps" 570 shift ;; 571 --nodeltarpms) 572 USEDELTARPMS=0 573 shift ;; 574 --nopatchrpms) 575 PATCHRPMS=0 576 shift ;; 577 --noprogress) 578 USEPROGRESS=0 579 shift ;; 580 --noresume) 581 NORESUME=1 582 shift ;; 583 --nogenerated) 584 GENERATED=0 585 shift ;; 586 --noproxy) 587 unset http_proxy 588 unset ftp_proxy 589 shift ;; 590 -o) 591 SKIPOPTIONAL=1 592 shift ;; 593 --offline) 594 OFFLINE=1 595 SUSEVERSION="*[0-9]" 596 shift ;; 597 --older-than) 598 if [[ $2 -ge 1 && $2 -lt 10000 ]] ; then 599 DAYSOLDER=$2 600 else 601 myError 0 "Invalid number of days: $2" 602 exit 2 603 fi 604 shift 2 ;; 605 --only) 606 ONLYINSTALLEDUSERRPMS=1 607 shift ;; 608 --product) 609 SUSEPRODUCT=$2 610 VERSIONOVERRIDE=1 611 shift 2 ;; 612 --proxy) 613 if [[ $2 == http://*([^\/])/ ]] ; then 614 export http_proxy=$2 615 export https_proxy=$2 616 export ftp_proxy=$2 617 if [[ $USERSYNCPROXY -eq 1 ]] ; then 618 RSYNC_PROXY=$2 619 RSYNC_PROXY=${RSYNC_PROXY##*://} 620 export RSYNC_PROXY=${RSYNC_PROXY%/} 621 fi 622 else 623 echo "Proxy must start with http:// and end with / (e.g. http://proxy:8080/)" 624 exit 2 625 fi 626 shift 2 ;; 627 --proxy-digest|--proxydigest) 628 PROXYDIGEST=1 629 shift ;; 630 --proxyuser) 631 PROXYUSER=$2 632 shift 2 ;; 633 --proxypasswd) 634 PROXYPASS=$2 635 shift 2 ;; 636 -q|--quiet) 637 VERBOSE=0 QUIET=1 638 shift ;; 639 -r|--remove) 640 REMOVE=1 641 shift ;; 642 -s|--security) 643 SECURITY=1 644 GENERATED=0 # speed up checking a little bit 645 shift ;; 646 --safemode) 647 SAFEMODE=1 648 shift ;; 649 --server) 650 UPDATESERVERLIST=1 651 shift ;; 652 --src|--source) 653 SRCRPMS=$2 654 shift 2 ;; 655 --suseuser) 656 HTTPUSER=$2 657 shift 2 ;; 658 --susepasswd|susepassword) 659 HTTPPASSWD=$2 660 shift 2 ;; 661 --suseversion) 662 SUSEVERSION=$2 663 NODOTSUSEVERSION=${SUSEVERSION//./} 664 VERSIONOVERRIDE=1 665 shift 2 ;; 666 --testmode) 667 TESTMODE=1 668 shift ;; 669 -u|--update) 670 UPDATEPACKAGELIST=1 671 shift ;; 672 --usecurl|--use-curl) 673 USECURL=1 674 USEDIR=1 675 shift;; 676 --usedir) 677 USEDIR=1 678 shift ;; 679 -v|--verbose) 680 QUIET=0 VERBOSE=$((VERBOSE+1)) 681 shift ;; 682 --version) 683 echo "fou4s v$FOUVERSION (c) 2002-2009 Markus Gaugusch <fou4s@gaugusch.at>" 684 exit ;; 685 -w) 686 UPDATESUSESERVERS=1 687 shift ;; 688 --) 689 shift # skip "--" 690 USERRPMS="$USERRPMS $*" # eat up all remaining params 691 [[ $# -ge 1 && $ONLYINSTALLEDUSERRPMS -eq 0 && $USECACHE -eq 2 ]] \ 692 && USECACHE=1 693 # level 2 cache is invalid with user specified rpms 694 set -- # set them to null to be explicit 695 break ;; 696 *) 697 myError 0 "Error: Unkown option: $1 (use -h for help)" 698 exit 3 ;; 699 esac 700 done 701 } # checkParameters 702 703 704 ################################ checkOption 705 # Verifies one config file option 706 # Parameters: 707 # $1 Value from config file 708 # $2 Option name 709 # $3 original value 710 # $4 If it is "bool", only 0/no/false or 1/yes/true is valid 711 # If it is "range", parameters $4/$5 are used 712 # $5 start range 713 # $6 end range 714 function checkOption() 715 { 716 local optionvalue="$1" option="$2" defaultvalue="$3" type="$4" 717 local rangestart="$5" rangeend="$6" 718 if [[ $type == bool ]] ; then 719 case "$optionvalue" in 720 0|false|no|off) 721 echo 0 722 myEcho 3 Found bool option $option with value 0 >&2 ;; 723 1|true|yes|on) 724 echo 1 725 myEcho 3 Found bool option $option with value 1 >&2 ;; 726 *) 727 echo "$defaultvalue" 728 myError 0 "ERROR: Invalid value for $option in config file $CONFIGFILE." >&2 729 myError 0 "Value must be 0/off or 1/on. Using default $defaultvalue" >&2 730 esac 731 elif [[ $type == range ]] ; then 732 if [[ $optionvalue -ge $rangestart && $optionvalue -le $rangeend ]] ; then 733 myEcho 3 "Found range option $option with value $optionvalue" >&2 734 echo "$optionvalue" 735 else 736 echo "$defaultvalue" 737 myError 0 "ERROR: Invalid value for $option in config file $CONFIGFILE." >&2 738 myError 0 "Value must be $rangestart..$rangeend, Using default $defaultvalue" >&2 739 fi 740 else 741 echo "$optionvalue" 742 myEcho 3 "Found option $option with value(s)" $optionvalue >&2 743 fi 744 } # checkOption 745 746 747 ################################ fixperms 748 # Fixes permissions of package description file on SuSE 8.1+ for group fou4s 749 function fixperms() 750 { 751 local answer allow=0 dir 752 if [[ $EUID -ne 0 ]] ; then 753 myError 0 "Error: you must be root to fix permissions!" 754 exit 4 755 fi 756 echo -e $COL_YELLOW 757 cat << _EOF 758 Allowing fou4s group members to access the description file is not considered 759 to be harmful to the system security in any way. It just allows fou4s to be run 760 by a non-root user to download packages. Answering no to the following question 761 will remove the rights. 762 _EOF 763 echo -e $COL_NORM 764 myRead "Allow group fou4s access to the description file (y/n)?" 765 if [[ $answer == y ]] ; then 766 if [[ `grep ^fou4s: /etc/group` != fou4s:* ]] ; then 767 myRead "Group fou4s does not exist, add it (y/n)?" 768 [[ $answer != y ]] && echo Aborting ... && return 769 groupadd fou4s 770 passwd -g fou4s -r # remove group password 771 fi 772 echo "Allowing group fou4s members to access to $PACKAGES81 ..." | fmt -$COLUMNS 773 allow=1 774 else 775 echo "Removing rights to access package description file ..." 776 fi 777 cd /var/adm 778 for dir in YaST InstSrcManager ; do 779 if [[ $allow -eq 1 ]] ; then 780 mode=g+x 781 group=fou4s 782 else 783 mode=g-x 784 group=root 785 fi 786 chgrp $group YaST YaST/InstSrcManager 787 chmod $mode YaST YaST/InstSrcManager 788 cd YaST/InstSrcManager 789 chgrp $group IS_CACHE_0x* IS_CACHE/0x*/DATA IS_CACHE/0x*/DATA/descr 790 chmod $mode IS_CACHE_0x* IS_CACHE/0x*/DATA IS_CACHE/0x*/DATA/descr 791 chgrp $group $PACKAGES81 792 done 793 exit 0 794 } # fixperms 795 796 ################################ installCronjob 797 # Copy example cronjob to /etc/cron*, depending on workstation or server 798 # config to cron.daily or cron.d 799 function installCronjob() 800 { 801 local cronfile time crondest ok=0 dirs="examples /usr/share/doc/packages/fou4s ." 802 local hour=25 min=99 803 if [[ $EUID -ne 0 ]] ; then 804 myError 0 "ERROR: You must run fou4s as root!" 805 exit 2 806 fi 807 umask g-w # for safety - fou4s members should not edit cronjobs! 808 for dir in $dirs ; do 809 if [[ -f $dir/fou4s-crontab ]] ; then 810 oldjob=/etc/cron.d/*fou4s*tab 811 for f in $oldjob ; do 812 [[ -f $f ]] && myWarn 0 "Warning: Old cron job detected: $f" 813 done 814 if [[ $CRONSERVER -eq 1 ]] ; then 815 while [ $ok -eq 0 ] ; do 816 echo -n "Please enter time for update checking (e.g. 3:43): " 817 read time 818 time=${time//[^0-9:]/} 819 hour=${time%%:*} 820 min=${time##*:} 821 [[ -n $min && -n $hour && $hour -ge 0 && $hour -le 23 && \ 822 $min -ge 0 && $time = *:* && $min -le 59 ]] || continue 823 ok=1 824 mmin=$((min+10)) 825 mhour=$hour 826 if [[ $min -ge 50 ]] ; then 827 mhour=$((mhour+1)) 828 [[ $mhour -gt 23 ]] && mhour=0 829 mmin=$((min+10-60)) 830 fi 831 done 832 if [[ -f /etc/cron.d/fou4s ]] ; then 833 myWarn 0 -n "File /etc/cron.d/fou4s already exists - overwrite (y/n)? " 834 myRead "" 835 [[ $answer != y ]] && echo "Not updating crontab ..." && break 836 fi 837 cat $dir/fou4s-crontab | sed "s/^5 6/$min $hour/g" | \ 838 sed "s/^17 6/$mmin $mhour/g" > /etc/cron.d/fou4s 839 else # workstation 840 for c in daily monthly ; do 841 if [[ -f /etc/cron.$c/fou4s ]] ; then 842 myWarn 0 -n "File /etc/cron.$c/fou4s already exists - overwrite (y/n)? " 843 myRead "" 844 [[ $answer != y ]] && continue 845 fi 846 cp $dir/fou4s-crontab.workstation.$c /etc/cron.$c/fou4s 847 chmod +x /etc/cron.$c/fou4s 848 done 849 fi 850 ok=1 851 myNote 0 "Crontab installation finished! Fou4s will now check for updates and download them automatically every day. Notifications about new updates are sent as mail to root." | fmt -$COLUMNS 852 break 853 fi 854 done 855 if [[ $ok -eq 0 ]] ; then 856 echo "Could not find cronjob templates in one of the follwing directories:" 857 echo $dirs 858 fi 859 exit 0 860 } # installCronjob 861 862 ################################ get81packagedescriptions 863 # Get "packages" file for suse 8.1+. It contains architecture information 864 # for packages that are not installed. 865 # This is needed, because the new update descriptions of 8.1+ don't 866 # contain arch information! 867 function get81packagedescriptions() 868 { 869 local server 870 for server in $SERVERLIST ; do 871 if [[ $server == *tp://* ]] && \ 872 [[ $server != *$ARCH/update/$SUSEPRODUCT$SUSEVERSION* ]] ; then 873 echo Getting package description file from $server ... | fmt -80 874 getremotefile --output-document $CACHEDIR/descr_packages.$SUSEVERSION $server/$ARCH/$SUSEVERSION/suse/setup/descr/packages 875 break 876 fi 877 done 878 exit 0 879 } # get81packagedescriptions 880 881 882 ################################ showProgress 883 # Shows a progress bar and a percentage value 884 # UsedBy: checkPackage, processServerList 885 # Parameters: 886 # $1: index 887 # $2: max 888 # $3: special: 889 # if 1, then show bar with 100% 890 # if 2, then show bar filled with "o", not "#" 891 function showProgress() 892 { 893 local index=$1 max=$2 len special=$3 bar bl restlen 894 local percent=$((index*100/max)) 895 [[ $special == 1 ]] && percent=100 896 bl="................................." # blank bar 897 bar="#################################" # filled bar 898 if [[ $NODOTSUSEVERSION -ge 110 ]] ; then 899 if [[ $3 == 2 ]] ; then 900 bar="ooooooooooooooooooooooooooooooooo" # pass 1 bar 901 pass="1/2" 902 else 903 bl="ooooooooooooooooooooooooooooooooo" # pass 2 bar 904 pass="2/2" 905 fi 906 fi 907 len=$((percent/3)) 908 restlen=$((33-len)) 909 [[ $restlen -lt 0 ]] && restlen=0 910 echo -n -e "$server: Checking $pass [${bar:0:$len}${bl:0:$restlen}] $percent % \r" 911 [[ $special == 1 ]] && echo # go to next line when forcing 100% ... 912 } # showProgress 913 914 915 ################################# myRecode 916 # SuSE update descriptions are UTF8 encoded. Usual Linux console 917 # and xterms are not configured to UTF8. Therefore we show it in 918 # ISO-8859-15 (western european, with euro symbol) charset 919 function myRecode() 920 { 921 [[ $DORECODE -eq 1 ]] && recode UTF8..ISO-8859-15 922 tr '' '\n' | tr '' '=' 923 if [[ $NODOTSUSEVERSION -ge 110 ]] ; then 924 sed 's/</</g' 925 sed 's/>/>/g' 926 sed 's/&/&/g' 927 fi 928 } 929 930 931 ################################ getremotefile 932 # Calls wget and deletes unnecessary index.html 933 # Parameters: 934 # $*: wget parameters 935 function getremotefile() 936 { 937 local f ret params user pass verbose=0 cont=0 cache=1 url opts quiet=0 recursive=0 bar=0 938 local outfile 939 params=`getopt -l user:,pass:,output-document:,verbose,bar,continue,nocache,quiet,recursive -o u:p:o:vbcnqr -n 'getremotefile' -- "$@"` 940 myEcho 2 "getremotefile $*" 941 test $? -ne 0 && myError 0 "Internal error in getremotefile. Info: $@" && exit 2 942 while [[ $# -gt 0 ]] ; do 943 case "$1" in 944 -u|--user) user=$2 ; shift ;; 945 -p|--pass) pass=$2 ; shift ;; 946 -o|--output-document) outfile=$2 ; shift ;; 947 -v|--verbose) verbose=1 ;; 948 -b|--bar) bar=1 ; shift ;; 949 -c|--continue) cont=1 ;; 950 -n|--nocache) cache=0 ;; 951 -q|--quiet) quiet=1 ;; 952 -r|--recursive) recursive=1 ;; 953 --) url=$2 ; shift ;; 954 *) url=$1 ;; 955 esac 956 shift 957 done 958 959 for f in index.htm* *\??=? ; do # remove index.html?x=y too 960 [[ -f $f ]] && rm -f "$f" 961 done 962 if [[ $USECURL -eq 0 ]] ; then ############ wget 963 [[ -n $user ]] && opts="$opts --http-user=$user" 964 [[ -n $pass ]] && opts="$opts --http-passwd=$pass" 965 [[ -n $outfile ]] && opts="$opts -O $outfile" 966 [[ $verbose -eq 0 && ($VERBOSE -eq 0 || $QUIET -eq 1) ]] && opts="$opts -q" 967 [[ $cont -eq 1 ]] && opts="$opts -c" 968 [[ $recursive -eq 1 ]] && opts="$opts -r" 969 [[ $cache -eq 0 ]] && opts="$opts --cache=off" 970 [[ "$url" == "-" ]] && opts="$opts -i -" && url= 971 972 if [[ $NORESUME -eq 1 ]] ; then 973 o=$outfile 974 if [[ -z $o ]] ; then 975 echo "fixme $url `basename "$url"`" 976 o=`basename "$url"` 977 else 978 echo "fixme outfile $o in $PWD" 979 fi 980 if [[ -f $o ]] ; then 981 myEcho 2 "Removing $outfile (don't want to work with incomplete files)" 982 echo rm $outfile 983 fi 984 #else 985 # if [[ `tail -1 $o` == -----END PGP SIGNATURE----- ]] ; then 986 # continue 987 # fi 988 fi 989 if [[ $VERBOSE -lt 3 ]] ; then 990 # suppress common errors, like 416 and timestamping turned off. 991 # The index.html?x=y are also suppressed for cleaner output 992 if [[ $bar -eq 0 ]] ; then 993 wget $GLOBALWGETOPTS $opts $url 2>&1 | grep --line-buffered -v "\(time-stamps turned off\|\?.=.\|ERROR 416: Requested Range Not Satisfiable\|ERROR 416: Unknown\)" 994 else 995 wget $GLOBALWGETOPTS $opts $url 996 fi 997 ret=${PIPESTATUS[0]} # thanks to lge 998 else # on debug level 3 I want to see it all! 999 wget $GLOBALWGETOPTS $opts $url 1000 ret=$? 1001 fi 1002 else ########## curl 1003 [[ -n $user && -n $pass ]] && opts="$opts -u $user:$pass" 1004 [[ -n $outfile ]] && opts="$opts -o $outfile" 1005 [[ $VERBOSE -eq 0 || $QUIET -eq 1 ]] && opts="$opts -s" 1006 [[ $VERBOSE -gt 1 ]] && opts="$opts -v" && outputfilter="|grep -v HTTP.server.doesn.t.seem.to.support.byte.ranges" 1007 [[ $cont -eq 1 ]] && opts="$opts -C -" 1008 [[ $recursive -eq 1 ]] && opts="$opts " # fixme 1009 # [[ $cache -eq 0 ]] && opts="$opts --nocache" 1010 if [[ "$url" == "-" ]] ; then 1011 opts="$opts -K -" 1012 url= 1013 fi 1014 [[ -z $outfile && -n $url ]] && opts="$opts -O" 1015 if [[ -z $url ]] ; then 1016 eval 'grep -v "^$" | sed "s/$/\"/g" | sed "s#^#-O\nurl = \"#g" | \ 1017 curl $GLOBALCURLOPTS $opts $url 2>&1' $outputfilter 1018 ret=$? 1019 else 1020 eval 'curl $GLOBALCURLOPTS $opts $url 2>&1' $outputfilter 1021 ret=$? 1022 fi 1023 fi 1024 f=index.htm* 1025 [[ $1 == http://* && $f == index.htm\* ]] && USEDIR=1 && myNote 2 "Could not read directory from $server!" 1026 for f in index.htm* *\??=? ; do # remove index.html?x=y too 1027 [[ -f $f ]] && rm -f "$f" 1028 done 1029 return $ret 1030 } # getremotefile 1031 1032 1033 ################################ checkDeleted 1034 # check for deleted files that are still in use 1035 function checkDeleted() 1036 { 1037 local p service 1038 [[ $QUIET -eq 0 ]] && myEcho 1 "Checking for deleted files ..." 1039 # PROCS=`lsof -n 2>/dev/null | grep RPMDELETE | grep -v fou4s | \ 1040 # cut -d " " -f 1 | sort | uniq` 1041 PROCS=$( lsof -n -F pcn 2>/dev/null | 1042 sed -ne $'/^p/h;/^c/H; 1043 /^n.*\(-RPMDELETE\|;\)/{ 1044 x;s/^.//; 1045 s/\\\n./\t/g;p; 1046 :1;n;/^p/!b1;h; 1047 }' 1048 ) # get the pid, too 1049 PROCS="`echo "$PROCS" | grep -v "\<fou4s\>"`" 1050 if [[ -n $PROCS ]] ; then 1051 echo 1052 myWarn 0 "WARNING" 1053 myWarn 0 "=======" 1054 echo 1055 myWarn 0 "The following processes are accessing deleted files:" 1056 echo 1057 myWarn 0 " PID COMMAND" 1058 echo "$PROCS" | while read pid name; do 1059 testname=${name%d} 1060 service=$( cd /etc/init.d && ls -1d * | grep -v -F '.rpmsave' \ 1061 | xargs -- grep -s -lE \ 1062 "(^[A-Z0-9]+_BIN=|^DAEMON=|\<startproc\>.*|^[A-Z0-9_]+=)([^ ]+/)?\<$testname" | head -1 1063 ) # the first two and the last pattern are redundant ... 1064 [[ -n $service ]] && service="(try /etc/init.d/$service restart)" 1065 [[ -n $service ]] && which rc$service &>/dev/null && service="(try rc$service restart)" 1066 [[ $name == mingetty ]] && service="(try killall mingetty)" 1067 [[ $name == java ]] && service="(try rctomcat restart)" 1068 printf "${COL_RED}%5i %-15s ${COL_CYAN}%s${COL_NORM}\n" "$pid" "$name" "$service" 1069 done 1070 echo 1071 myWarn 0 "Please restart these processes to finish the update." 1072 echo 1073 myNote 0 "You can check for used files using the command" 1074 myNote 0 "fou4s --checkdeleted $COL_NORM(can be abbreviated with --checkd)" 1075 echo or using the command 1076 myNote 0 "lsof -n | grep RPMDELETE" 1077 fi 1078 1079 if [[ $KERNELCHECK -eq 1 ]] ; then 1080 KERNELVER=${KERNELVER//-default/} 1081 KERNELVER=${KERNELVER//-smp/} 1082 KERNELVER=${KERNELVER//-bigsmp/} 1083 KERNELVER=${KERNELVER//-pae/} 1084 reboot=0 1085 newkernelver=`rpm -q --qf "%{VERSION}-%{RELEASE}" $KERNELPKG` 1086 newkernelbuild=`rpm -q --qf "%{BUILDTIME}" $KERNELPKG` 1087 if [[ -n $SUSEKERNELVER && -n $newkernelver && \ 1088 $SUSEKERNELVER != *$newkernelver* ]] ; then 1089 reboot=1 1090 elif [[ $NODOTSUSEVERSION -eq 82 ]] ; then 1091 # this function is a bit heuristic: if the running kernel 1092 # (/proc/version) is packaged less than 24 hours after it was built, 1093 # we assume that it corresponds to the currently installed kernel 1094 # package. This is because the version numbers are not compareable in 1095 # some SuSE versions (8.2 has always 2.4.20-4GB, no matter what the 1096 # RPM says). 1097 runningkernelbuild="`cat /proc/version | sed 's/SMP //g'`" 1098 runningkernelbuild=${runningkernelbuild##*#} 1099 runningkernelbuild=${runningkernelbuild#* } 1100 runningkernelbuild=`date "+%s" -d "$runningkernelbuild"` 1101 # we use a little bit more than one day (would be 86400 secs) 1102 # because it made problems with kernel 2.6.5-7.111 1103 if [[ $((newkernelbuild - runningkernelbuild)) -gt 100000 ]] ; then 1104 reboot=1 1105 fi 1106 myEcho 2 "Running kernel build: $runningkernelbuild, Installed kernel build: $newkernelbuild" 1107 fi 1108 if [[ $KERNELVER.1 == $newkernelver || $KERNELVER.2 == $newkernelver || $KERNELVER.3 == $newkernelver ]] ; then 1109 reboot=0 # bugfix for 64bit openSUSE 11.1 kernel, e.g. uname 2.6.27.19-3.2 vs. 2.6.27.19-3.2.1 RPM 1110 fi 1111 1112 if [[ $reboot -eq 1 ]] ; then 1113 echo 1114 myWarn 0 "The running kernel ($KERNELVER) is different from installed \ 1115 kernel ($newkernelver). You must reboot your machine to make the kernel update \ 1116 effective. If this notification is wrong, please contact fou4s@gaugusch.at and \ 1117 set KernelCheck=0 in fou4s.conf to disable it until a fix is available." \ 1118 | fmt -$COLUMNS 1119 fi 1120 fi 1121 myEcho 3 "Done checking for deleted files ..." 1122 return 0 1123 } # checkDeleted 1124 1125 1126 ################################ printUpdateInformation 1127 # Shows detailed information about an update 1128 # parameters: 1129 # $1: patch description file 1130 # $2: short description 1131 function printUpdateInformation() 1132 { 1133 local txt txtlen line pkgdescfile=$1 shortdesc=$2 len len2 1134 local lang gnal width=$((COLUMNS-1)) 1135 if [[ $VERBOSE -ge 1 ]] ; then 1136 echo -e $COL_CYAN 1137 line="======================================================================================================================================================================================================" 1138 [[ $newbuildtime != 0 ]] && date="(`date -d "1970-01-01 $newbuildtime sec" "+%Y-%m-%d"`) " 1139 txt=" Update Information for $COL_YELLOW${pkgdescfile##*/}$COL_CYAN $date" 1140 txtlen=$((${#txt}-${#COL_YELLOW}-${#COL_CYAN}+1)) 1141 len=$(( $width-$txtlen )) 1142 [[ $((len/2)) -ne $(( (len+1)/2 )) ]] && len2=$((len/2+1)) || len2=$((len/2)) 1143 len=$((len/2)) 1144 width=$((len+len2+txtlen)) # if width was odd 1145 echo -e ${line:0:$len}$txt${line:0:$len2} 1146 [[ -n $shortdesc ]] && echo -e $COL_WHITE$shortdesc$COL_CYAN | myRecode | sed 's/"/"/g' 1147 lang=$LANGUAGE gnal=$EGAUGNAL 1148 if [[ $NODOTSUSEVERSION -lt 101 ]] ; then 1149 checkLanguage "`awk "/Longdescription.$LANGUAGE:/,/$EGAUGNAL.noitpircsedgnol:/" $pkgdescfile`" || { lang=english gnal=Hsilgne ; } 1150 awk "/Longdescription.$lang:/,/$gnal.noitpircsedgnol:/" $pkgdescfile \ 1151 | tr --delete '\r' \ 1152 | sed 's/^- -/\n- /g'| sed '1d;$d' | myRecode | fmt -$width | grep -v "^$" 1153 else 1154 #echo "$longdesc" | myRecode | tr --delete '\r' | sed 's/"/"/g' | fmt -$width | grep -v "^$" 1155 echo "$longdesc" | myRecode | sed 's/"/"/g' 1156 fi 1157 echo -e ${line:0:$width}$COL_NORM # show this line only in length of the above 1158 #else 1159 # myNote 0 "----- Updates from $COL_YELLOW${pkgdescfile##*/}$COL_CYAN: " 1160 fi 1161 return 0 1162 } # printUpdateInformation 1163 1164 function showSummaryEntry() 1165 { 1166 local pre=$1 which=$2 txt=$3 size hdsize hdcomment="+" 1167 if [[ ${COUNTER[$which]} -gt 0 ]] ; then 1168 size=$((SIZES[$which]/1024)) 1169 hdsize=$((HDSIZES[$which]/1024)) 1170 dlsize=$((DLSIZES[$which]/1024)) 1171 [[ $hdsize -lt 0 ]] && hdsize=$((hdsize*-1)) && hdcomment="-" 1172 [[ $hdsize -eq 0 ]] && hdcomment="" 1173 #test $hdsize -eq 0 && hdsize="???" 1174 printf "$pre$COL_YELLOW%3d$COL_NORM $txt$COL_YELLOW%6d${COL_NORM}kB \ 1175 $COL_YELLOW%6s${COL_NORM}kB $COL_YELLOW%6s${COL_NORM}kB\n" ${COUNTER[$which]}\ 1176 $size $hdcomment$hdsize $dlsize 1177 fi 1178 return 0 1179 } # showSummaryEntry 1180 1181 function showSummary() 1182 { 1183 local prod=${SUSEPRODUCT:=SuSE} 1184 prod=${prod//\//} 1185 echo 1186 myEcho 0 "Update statistics for $prod $SUSEVERSION host $HOSTNAME (fou4s $FOUVERSION):" 1187 if [ $DAYSOLDER -gt 0 ] ; then 1188 myEcho 0 "Showing only updates older than $DAYSOLDER days" 1189 fi 1190 myEcho 0 " Size After Upd. To D/L" 1191 showSummaryEntry " " $_SECURITY "${COL_RED}security$COL_NORM update(s) " 1192 showSummaryEntry " " $_RECOMMENDED "${COL_CYAN}recommended$COL_NORM update(s) " 1193 showSummaryEntry " " $_YAST "YaST2 update(s) " 1194 showSummaryEntry " " $_OPTIONAL "optional update(s) " 1195 showSummaryEntry " " $_SCRIPT "script(s) " 1196 showSummaryEntry " " $_GENERATED "generated update(s) " 1197 showSummaryEntry "" $_ALL "update(s), total " 1198 } # showSummary 1199 1200 1201 ################################ getKernelVersion 1202 # Get info about running SuSE-kernel 1203 # UsedBy: updateRpmCache 1204 # Parameters: none 1205 function getKernelVersion() 1206 { 1207 local pkg version 1208 pkg=`rpm -qf /boot/vmlinuz 2>/dev/null` 1209 version="`grep "\((root@[-a-zA-Z0-9]*\.suse\.\|-default \|-smp \|-bigsmp \|-pae \)" < /proc/version`" 1210 version=${version%%(*} 1211 version=${version//Linux version } 1212 if [[ $NODOTSUSEVERSION -lt 112 && $KERNELCHECK -eq 1 && `rpm -qf /boot/vmlinuz 2>/dev/null | wc -l` -gt 1 ]] ; then 1213 myWarn 0 "More than one kernel is installed! Please set KernelCheck=0 in fou4s.conf or remove other kernels"|fmt -$COLUMNS 1214 KERNELCHECK=0 1215 KERNELBACKUP=0 1216 elif [[ -z $pkg ]] ; then 1217 myWarn 2 "No SuSE kernel installed - can't check Kernel updates" 1218 KERNELCHECK=0 1219 KERNELBACKUP=0 1220 elif [[ -z $version ]] ; then 1221 myWarn 2 "No SuSE kernel running - can't check Kernel updates" 1222 KERNELCHECK=0 1223 KERNELBACKUP=0 1224 else 1225 KERNELPKG=${pkg%%-[2-9]*} 1226 SUSEKERNELVER=$version 1227 myNote 2 "Found suse kernel $KERNELPKG $SUSEKERNELVER" 1228 fi 1229 } 1230 1231 1232 ################################ updateRpmCache 1233 # Make sourceable cache of rpm database 1234 # UsedBy: main 1235 # Parameters: 1236 # $1: if this is "force", creation is forced 1237 function updateRpmCache() 1238 { 1239 local force=0 ver rpmoutput 1240 RPMCACHECOMPLETE=0 1241 [[ $OFFLINE -eq 1 ]] && return || [[ -n $HOSTEXEC ]] && force=1 1242 [[ $UPDATESERVERLIST -eq 1 ]] && return 1243 [[ $1 == force ]] && force=1 1244 [[ -z $HOSTEXEC && $RPMVER -eq 30 && /var/lib/rpm/packages.rpm -nt $RPMCACHE ]] && force=1 1245 [[ -z $HOSTEXEC && $RPMVER -ge 40 && /var/lib/rpm/Packages -nt $RPMCACHE ]] && force=1 1246 if [[ $RPMCACHE -nt /proc/self/cmdline ]] ; then 1247 myWarn 0 "Warning: Time skew detected - fou4s cache newer than system time!" 1248 cleanCache 1249 force=1 1250 fi 1251 if [[ ! -f $RPMCACHE || $force -eq 1 ]] ; then 1252 trap 'exec 1>&10-; myError 0 "updateRpmCache FAILED"; rm -f "$RPMCACHE.new; exit 13"' EXIT 1253 set -e # exit if any of the below fails ... 1254 myEcho 2 "Updating rpm cache" 1255 query="%{NAME}='%{VERSION}-%{RELEASE} %{BUILDTIME} %{ARCH} %{SIZE}'\n" 1256 [[ -n $HOSTEXEC ]] && query="\"$query\"" 1257 # by l.g.e 1258 if [[ -z $HOSTEXEC ]] ; then 1259 rpmoutput=`rpm -qa --queryformat "$query"` 1260 else 1261 myNote 2 "Getting RPM cache from remote host $HOSTNAME" 1262 rpmoutput=`$HOSTEXEC -- " 1263 SuSE-release v1.2 2>/dev/null 1264 rpm -qa --queryformat "$query" 1265 "` 1266 ver=(`echo "$rpmoutput" | head -1`) 1267 if [[ ${ver[0]} = SuSE-Release* ]] ; then 1268 SUSEVERSION=${ver[1]} 1269 NODOTSUSEVERSION=${ver[2]} 1270 ARCH=${ver[3]} 1271 SUSEPRODUCT=${ver[4]} 1272 if [[ ${ver[0]} = SuSE-Release-v1.1: ]] ; then 1273 KERNELVER=${var[5]} # only check kernelver with new suse-release 1274 elif [[ ${ver[0]} = SuSE-Release-v1.2: ]] ; then 1275 KERNELVER=${var[5]} # only check kernelver with new suse-release 1276 MACHINEARCH=${var[6]} 1277 VALIDARCHS=${ver[7]//+/ } 1278 fi 1279 RPMCACHE=$CACHEDIR/.cache.$HOSTNAME/rpmcache.$SUSEVERSION # rebuild 1280 myNote 2 "New SuSE-release: $SUSEPRODUCT $SUSEVERSION ($ARCH)" 1281 rpmoutput=`echo "$rpmoutput" | grep -v ^SuSE-Release` 1282 else 1283 if [[ $VERSIONOVERRIDE -eq 0 ]] ; then 1284 myError 0 "Could not determine remote SuSE-release. Install at \ 1285 least fou4s 0.10 or override with --suseversion and --product"| fmt -$COLUMNS 1286 fi 1287 fi 1288 fi 1289 echo "RPMCACHEVERSION=$RPMCACHEVER" > $RPMCACHE.new 1290 echo "$rpmoutput" | 1291 sed 'h; # remember line 1292 s/^.*=/=/; # cut 1293 x; # exchange 1294 s/=.*$//; # cut 1295 s/[^A-Za-z0-9_]/_/g; # valid identifier 1296 s/^/pkg_/; # prefix 1297 G; # append again 1298 s/'$'\\\n''//; # newer sed would say s/\n//;' >> $RPMCACHE.new 1299 # fail if either rpm or sed had problems 1300 [[ -z ${PIPESTATUS[*]//0} ]] 1301 echo "SUSEVERSION=$SUSEVERSION" >> $RPMCACHE.new 1302 echo "NODOTSUSEVERSION=$NODOTSUSEVERSION" >> $RPMCACHE.new 1303 echo "ARCH=$ARCH" >> $RPMCACHE.new 1304 echo "MACHINEARCH=$MACHINEARCH" >> $RPMCACHE.new 1305 echo "SUSEPRODUCT=$SUSEPRODUCT" >> $RPMCACHE.new 1306 echo "HOSTNAME=$HOSTNAME" >> $RPMCACHE.new 1307 echo "RPMCACHECOMPLETE=1" >> $RPMCACHE.new 1308 echo "VALIDARCHS=\"$VALIDARCHS\"" >> $RPMCACHE.new 1309 mv $RPMCACHE.new $RPMCACHE # atomic. RPMCACHECOMPLETE should no longer be necessary 1310 set +e # restore default handling 1311 trap - EXIT 1312 rm -f $DESCCACHE 2>/dev/null # remove old patch description cache for safety 1313 DESCCACHE=$CACHEDIR/.cache.$HOSTNAME/descriptioncache.$SUSEVERSION # rebuild 1314 else 1315 myEcho 2 "Not updating rpm cache" 1316 fi 1317 } # updateRpmCache 1318 1319 ################################ updateDescriptionCache 1320 # Make sourceable cache of update descriptions 1321 function updateDescriptionCache() 1322 { 1323 local p p1 1324 rm -f $DESCCACHE.new 1325 # not writeable -> abort 1326 echo "DESCRIPTIONCACHE_VERSION='1.4'" 2>/dev/null >$DESCCACHE.new || return 1 1327 echo "DC_ARCH='$ARCH'" >> $DESCCACHE.new 1328 echo "DC_PRODUCT='$SUSEPRODUCT'" >> $DESCCACHE.new 1329 echo "DC_VERSION='$SUSEVERSION'" >> $DESCCACHE.new 1330 echo "DC_SERVERLIST=\"$SERVERLIST\"" >> $DESCCACHE.new 1331 echo "DC_LANGUAGE='$LANGUAGE'" >> $DESCCACHE.new 1332 for p in ${!packageinfo_*} ${!package_*} ${!longdesc_*} ${!license_*} ${!shortdesc_*} ${!dlfile1_*} ${!server1_*} ; do 1333 p1=${!p} 1334 echo "$p='${p1//\'/\"}'" >> $DESCCACHE.new 1335 done 1336 mv $DESCCACHE.new $DESCCACHE 1337 return 0 1338 } # updateDescriptionCache 1339 1340 1341 ################################ cleanCache 1342 function cleanCache() 1343 { 1344 rm -rf $CACHEDIR/.cache.$HOSTNAME 1345 mkdir $CACHEDIR/.cache.$HOSTNAME 1346 return 0 1347 } # cleanCache 1348 1349 1350 ################################ parsePatchesXML 1351 # Parse the "patches.xml" file from SuSE 10.1 .. 10.3 1352 # Parameters: 1353 # $1: 1354 # -f: get filenames (patch-*.xml) 1355 # -c: get filenames with bad checksums 1356 # $2: prefix for all printed filenames 1357 1358 function parsePatchesXML() 1359 { 1360 local opt=$1 prefix=$2 filesum checksum 1361 1362 cat patches.xml | $XMLP | while read line ; do 1363 case $line in 1364 /patches/patch/checksum=*) 1365 checksum=${line##*=} 1366 ;; 1367 /patches/patch/location/@href=*) 1368 patch=${line##*/} 1369 if [[ -f $patch ]] ; then 1370 filesum=`sha1sum $patch` 1371 filesum=${filesum%% *} 1372 fi 1373 [[ $filesum != $checksum || $opt == -f ]] && echo $prefix$patch 1374 [[ $filesum != $checksum && -f $patch ]] && rm $patch 1375 ;; 1376 esac 1377 done 1378 1379 } 1380 1381 1382 ################################ getDirectory 1383 # Get all files inside of all 'directory' files in the current directory 1384 # Parameters: 1385 # $1: Server URL, including "patches" directory 1386 # $2: Special fou4s update option: -f (only use for fou4s updates) 1387 function getDirectory() 1388 { 1389 local dir p url=$1 1390 if [[ $NODOTSUSEVERSION -lt 101 ]] ; then 1391 for dir in directory directory.* ; do 1392 [[ -f $dir ]] || continue 1393 if grep -q '\(<\|`\|\$\|\.\.\|/\)' $dir ; then 1394 myWarn 0 "Invalid content found in $PWD/$dir" 1395 rm -f $dir 1396 continue 1397 fi 1398 grep -v "^$" $dir | sed "s#^#$url#g" | getremotefile $AUTHOPTS $downloadopts - 1399 [[ $2 == -f ]] && break 1400 done 1401 fi 1402 if [[ $NODOTSUSEVERSION -lt 110 && $NODOTSUSEVERSION -ge 101 ]] ; then 1403 parsePatchesXML -c $url | getremotefile $AUTHOPTS $downloadopts - 1404 fi 1405 } # getDirectory 1406 1407 1408 ################################ betterArch 1409 # Check if one of the two given arch's is better than the other 1410 # Parameters: 1411 # $1: base arch 1412 # $2: arch for comparison 1413 # Return Value: 1414 # 0 if $1 is better or equal to $2, 1 otherwise (and in case of error) 1415 function betterArch() 1416 { 1417 local a i=0 a1=0 a2=0 1418 [[ $1 == $2 ]] && return 0 1419 if [[ $1 == @(${VALIDARCHS// /|}) && $2 == @(${VALIDARCHS// /|}) ]] ; then 1420 for a in $VALIDARCHS ; do 1421 i=$((i+1)) 1422 [[ $a == $1 ]] && a1=$i 1423 [[ $a == $2 ]] && a2=$i 1424 done 1425 [[ $a1 -lt $a2 ]] && return 0 1426 fi 1427 return 1 1428 } 1429 1430 1431 ################################ updatePackagelist 1432 # Get the package list from the server 1433 # Parameters: 1434 # $1: server name (e.g. ftp.gwdg.de) 1435 # $2: serverpath: directory on server, where updates are located 1436 # (e.g. /pub/linux/suse/i386/update/8.1/ 1437 function updatePackagelist() 1438 { 1439 local server=$1 serverpath=$2 dirspec rsyncopts=-qz err=0 recurse ret err q 1440 local downloadopts="-c" # default: medium verbosity FIXME -nv!! 1441 local servername 1442 1443 servername=${SERVERURL##*@} 1444 cd "$BASEDIR" 1445 mkdir -p "$DLPATH/$server/$serverpath/$PATCHDIR" || exit 1446 cd "$DLPATH/$server/$serverpath/$PATCHDIR" 1447 recurse= # recurse setting is needed when going over http 1448 [[ -n $serverpath ]] && serverpath=$serverpath/ 1449 if [[ $SERVERURL == *$SERVERPATH* ]] && \ 1450 [[ $SERVERURL == rsync://* ]] ; then 1451 if [[ $QUIET -eq 0 ]] ; then 1452 myNote 0 "Generating patch descriptions from $servername" | fmt -$COLUMNS 1453 fi 1454 for g in "$DIRNAME/gpd.sh" /usr/bin/gpd.sh /usr/local/bin/gpd.sh ; do 1455 [[ -x $g ]] && gpd=$g && break 1456 g="" 1457 done 1458 [[ -n $gpd ]] && $gpd -v $VERBOSE --server $SERVERURL -q 1 --destpath .. || myError 0 "Error while calling gpd.sh!" 1459 logWrite 1 "Updated patch descriptions from $servername" 1460 return 1461 fi 1462 if [[ $QUIET -eq 1 ]] ; then 1463 downloadopts="-q -c" # quiet mode 1464 else 1465 myNote 0 "Getting patch descriptions from $servername" 1466 if [[ $VERBOSE -ge 1 ]] ; then 1467 downloadopts="-c" #default wget is very verbose, only set continue option 1468 rsyncopts=-vz 1469 fi 1470 fi 1471 if [[ $SERVERURL == ftp://* ]] ; then 1472 dirspec='*' # ftp servers need * after the path 1473 else 1474 dirspec= # http servers don't work with the * 1475 recurse="-r" # recursive option 1476 fi 1477 # check for fou4s updates 1478 if [[ $CHECKFOU -eq 1 && $NODOTSUSEVERSION -lt 101 ]] ; then 1479 myEcho 2 "Getting fou4s patches ..." 1480 if [[ $USEDIR -eq 1 ]] ; then 1481 [[ -f directory ]] && mv directory directory.old 1482 getremotefile -q --nocache $downloadopts "http://fou4s.gaugusch.at/${BETA}patches/directory" 1483 getDirectory "http://fou4s.gaugusch.at/${BETA}patches/" -f 1484 [[ -f directory ]] && rm -f directory.old || mv directory.old directory 1485 else 1486 getremotefile -q --nocache $downloadopts -r "http://fou4s.gaugusch.at/${BETA}patches/" 1487 fi 1488 CHECKFOU=0 # disable fou4s check when processing other servers 1489 fi 1490 # get YOU update descriptions 1491 if [[ $SERVERURL == @(rsync://*|*:/[^/]*) ]] ; then 1492 rsync $RSYNCOPTS $rsyncopts "$SERVERURL/$SERVERPATH/$PATCHDIR/*" . 1493 ret=$? 1494 else 1495 if [[ $USEDIR -eq 1 ]] ; then 1496 if [[ $NODOTSUSEVERSION -ge 110 ]] ; then 1497 test -f repomd.xml && mv repomd.xml repomd.xml.old 1498 getremotefile $AUTHOPTS $downloadopts $q -n "$SERVERURL/$serverpath$PATCHDIR/repomd.xml?" 1499 if [ ! -f repomd.xml ] ; then 1500 test -f repomd.xml.old && mv repomd.xml.old repomd.xml 1501 myWarn 0 "Description file could not be downloaded for $SERVERURL: repomd.xml" 1502 fi 1503 1504 for infofile in primary updateinfo deltainfo ; do 1505 infofilename=`$XMLP < repomd.xml | grep "$infofile.xml.gz\$" | sed 's/.*=repodata.//'` 1506 myEcho 3 "fn: $infofilename f: $infofile" 1507 test -f $infofile.xml.gz && mv "$infofile.xml.gz" "$infofile.xml.old" 1508 test -z $infofilename && continue 1509 getremotefile $AUTHOPTS $downloadopts $q "$SERVERURL/$serverpath$PATCHDIR/$infofilename" 1510 test -f $infofilename || continue 1511 test $infofilename = $infofile.xml.gz || mv $infofilename $infofile.xml.gz 1512 if [[ ! -f $infofile.xml.gz && $infofile != deltainfo ]] ; then 1513 myWarn 0 "Description file could not be updated for $SERVERURL: $infofile" 1514 for i in *.old ; do 1515 test -f $i && mv $i ${i%%old}.gz 1516 done 1517 break 1518 fi 1519 done 1520 else 1521 [[ $NODOTSUSEVERSION -ge 101 ]] && dir=patches.xml || dir=directory.3 1522 [[ $VERBOSE -eq 0 || $QUIET -eq 1 ]] && q= || q=-v 1523 [[ -f $dir ]] && mv "$dir" "$dir.old" 1524 getremotefile $AUTHOPTS $downloadopts $q "$SERVERURL/$serverpath$PATCHDIR/$dir" 1525 ret=$? 1526 if [[ $ret -ne 0 && -f $dir.old ]] ; then 1527 mv "$dir.old" "$dir" 1528 fi 1529 getDirectory "$SERVERURL/$serverpath$PATCHDIR/" 1530 fi 1531 else 1532 getremotefile $AUTHOPTS -q $downloadopts $recurse "$SERVERURL/$serverpath$PATCHDIR/$dirspec" 1533 ret=$? 1534 fi 1535 fi 1536 [[ $ret -ne 0 ]] && myError 0 "Warning: download error $ret from $server" && err=1 1537 if [[ $err == 0 ]] ; then 1538 logWrite 1 "Updated patch descriptions from $SERVERURL" 1539 else 1540 logWrite 0 "Error while updating patch descriptions from $SERVERURL" 1541 fi 1542 cd "$BASEDIR" 1543 } # updatePackagelist 1544 1545 1546 ################################ updateConfigFile 1547 # Replace value in fou4s.conf 1548 # Parameters: 1549 # $1: Key 1550 # $2: Value 1551 function updateConfigFile() 1552 { 1553 local key=$1 value=$2 oldkey newcfgfile 1554 1555 if [[ -n `grep ^$key= $CONFIGFILE` ]] ; then 1556 if [[ `grep "^$key=" $CONFIGFILE | wc -l` -gt 1 ]] ; then 1557 oldkey=`grep "^$key=" $CONFIGFILE| head -1` 1558 oldkey=${oldkey##$key=} 1559 myEcho 1 "Replacing first $key: $oldkey" 1560 else 1561 oldkey= # just replace existing key 1562 fi 1563 myEcho 3 "Key $key Oldkey $oldkey Value $value" 1564 newcfgfile=`sed "s!^$key=$oldkey.*!$key=$value!g" < $CONFIGFILE` 1565 if [[ -z $newcfgfile ]] ; then 1566 myError 0 "Internal error - cannot update config file!" 1567 else 1568 echo "$newcfgfile" > $CONFIGFILE 1569 fi 1570 else # append new key 1571 newcfgfile="`grep -v "^$key=" $CONFIGFILE`" 1572 echo "$newcfgfile" > $CONFIGFILE 1573 echo $key=$value >> $CONFIGFILE 1574 fi 1575 return 0 1576 } 1577 1578 1579 ################################ updateServerlist 1580 # Get the ftp server list from www.suse.de and install in /etc/suseservers 1581 function updateServerlist() 1582 { 1583 local filename=suseservers.txt 1584 if [[ $UPDATESUSESERVERS -eq 1 ]] ; then 1585 if [[ $EUID -eq 0 ]] ; then 1586 cd /etc 1587 rm -f suseservers.bak 2>/dev/null 1588 [[ -f suseservers ]] && cp suseservers suseservers.bak 1589 if [[ $NODOTSUSEVERSION -eq 101 && $SUSEVERSION = 10 ]] ; then 1590 echo https://nu.novell.com/repo/$RCE/SLES10-SP2-Updates/sles-10-$MACHINEARCH > /etc/suseservers 1591 elif [[ $NODOTSUSEVERSION -lt 103 ]] ; then 1592 # the following line is from online_update_start.ycp :-) 1593 TIMEZONE=`grep "^TIMEZONE=".*"$" /etc/sysconfig/clock | tail -1 | sed 's/TIMEZONE="//g'| sed 's/"//g'` 1594 [[ -n $TIMEZONE ]] && TIMEZONE="&timezone=$TIMEZONE" 1595 url="http://www.suse.de/cgi-bin/suseservers.cgi?product=${SUSEPRODUCT:-SUSE%20LINUX}&version=$SUSEVERSION&basearch=$ARCH&arch=$MACHINEARCH&timezone=$TIMEZONE" 1596 [[ -n $SUSEPRODUCT ]] && url="$url&business=1&yast2-online-update=2.9.21-0.3&yast2-packagemanager=2.9.67-0.3.1" 1597 getremotefile -q --output-document /etc/suseservers "$url" 1598 ret=$? 1599 if [[ $ret -ne 0 ]] ; then 1600 myWarn 0 "Warning: download error $ret while retrieving suseservers" 1601 fi 1602 else ## openSUSE 10.3 has automatic mirror selection through download.opensuse.org 1603 echo http://download.opensuse.org/ > /etc/suseservers 1604 fi 1605 cd "$BASEDIR" 1606 else 1607 myError 0 "ERROR: You must run fou4s as root to update /etc/suseservers!" 1608 exit 5 1609 fi 1610 fi 1611 echo The download server will be written to $CONFIGFILE 1612 if [[ ! -f /etc/suseservers ]] ; then 1613 echo "Could not find /etc/suseservers. Please run fou4s --server -w to get it." 1614 exit 6 1615 fi 1616 if [[ ! -w $CONFIGFILE ]] ; then 1617 myError 0 "ERROR: No permission to write to $CONFIGFILE - aborting" 1618 exit 7 1619 fi 1620 if [[ `cat /etc/suseservers | wc -l` -gt 1 ]] ; then 1621 select server in `grep -v "^#" /etc/suseservers | sed 's/;.*//g'` ; do 1622 cd "$BASEDIR" 1623 break 1624 done 1625 else 1626 server=`cat /etc/suseservers` 1627 fi 1628 if [[ $server == ftp://* ]] ; then 1629 myRead "Use HTTP instead of FTP (recommended, but doesn't work on all servers!)? (y/n)" 1630 if [[ $answer == y ]] ; then 1631 server="http://${server##ftp://}" # strip ftp:// and add http:// 1632 echo Using $server ... 1633 fi 1634 fi 1635 updateConfigFile Server $server 1636 } # updateServerList 1637 1638 1639 ################################ prepareKernelUpdate 1640 # Makes a backup of the existing kernel before updating it. 1641 function prepareKernelUpdate() 1642 { 1643 local i 1644 if [[ ! -f /boot/vmlinuz ]] ; then 1645 myWarn 0 "Warning! Could not find old kernel! Can't make backup." 1646 return 1 1647 fi 1648 myNote 0 "Creating backup of old Kernel (to /boot/vmlinuz.fou4s) ..." 1649 myNote 0 "Remember to create an appropriate entry in your grub or lilo configuration." 1650 for i in vmlinuz System.map initrd ; do 1651 rm -f /boot/$i.fou4s 1652 [[ -f /boot/$i ]] && cat < /boot/$i > /boot/$i.fou4s 1653 done 1654 rm -rf /lib/modules/[23].[0-9]*.fou4s 1655 cp -a /lib/modules/$KERNELVER /lib/modules/$KERNELVER.fou4s 1656 } 1657 1658 1659 ################################ postKernelUpdate 1660 # post-kernel-installation work for kernel backup 1661 function postKernelUpdate() 1662 { 1663 local backup="`echo /lib/modules/[23].[0-9]*.fou4s`" 1664 local target=${backup%%.fou4s} 1665 myEcho 2 "Finishing Kernel backup ... ($backup, $target)" 1666 if [[ -d $backup ]] ; then 1667 if [[ ! -d $target ]] ; then 1668 ln -s /lib/modules/$KERNELVER.fou4s /lib/modules/$KERNELVER 1669 else 1670 myWarn 0 "Could not rename old modules back to original name (`basename "$target"`). Either the kernel update failed or the new kernel uses the same directory name (common on older SuSE 8.x) In case of problems, you must rename the modules directory manually (the backup is at $backup)" | fmt -$COLUMNS 1671 fi 1672 fi 1673 } 1674 1675 1676 ################################ suDo 1677 # parameter: 1678 # $*: command to execute via su (to get rid of group fou4s when working as root) 1679 function suDo() 1680 { 1681 # we use an additional 'su' to get rid of group fou4s 1682 if [[ $EUID -eq 0 ]] ; then 1683 su - root -c "$*" # FIXME check su call below 1684 # su - root -c '$0 "$@"' -- "$@" #by l.g.e, doesn't work on some machines? 1685 else 1686 "$@" 1687 fi 1688 } 1689 1690 1691 ################################ rpmInstall 1692 # parameter: 1693 # $*: filename1.rpm filename2.rpm ... 1694 function rpmInstall() 1695 { 1696 local currentversion 1697 local allpkgs="$*" count=$# output p lang gnal currentdir cmd 1698 local postKernel=0 # do kernel-update post-install operations (backup) 1699 if [[ -n $EXPORTFILE && $EXPORT -eq 1 ]] ; then 1700 for p in $allpkgs ; do 1701 addToRpmExportList $p 1702 done 1703 return 1704 fi 1705 if [[ $EUID -ne 0 && $TESTMODE -eq 0 && $1 != *.src.rpm ]] ; then 1706 myError 0 "Error: You must be root to install packages!" 1707 return 1708 fi 1709 if [[ $count == 1 ]] ; then 1710 echo "Installing ${allpkgs##*/}" 1711 else 1712 echo 1713 echo -e "Installing the following $COL_YELLOW$count$COL_NORM package(s): " 1714 for p in $allpkgs ; do 1715 output="$output${p##*/} " 1716 done 1717 echo "$output" | fmt -$COLUMNS 1718 echo 1719 fi 1720 1721 [[ $TESTMODE -eq 0 && $KERNELBACKUP -eq 1 && $allpkgs == *$KERNELPKG* ]] && \ 1722 prepareKernelUpdate && postKernel=1 1723 #we can use -U in favor of -F because the package is either already 1724 #installed, or HAS to be installed (because of -f option) 1725 [[ $TESTMODE -eq 1 ]] && test=--test 1726 cmd="rpm -Uvh $test $GLOBALRPMOPTS $allpkgs" 1727 if [[ $VERBOSE -ge 1 ]] ; then 1728 rpmresult="" 1729 suDo $cmd 1730 else 1731 rpmresult="`suDo $cmd 2>&1`" 1732 fi 1733 if [[ $? -eq 0 ]] ; then 1734 [[ $postKernel -eq 1 ]] && postKernelUpdate 1735 [[ $TESTMODE -eq 1 ]] && test=" (test mode)" 1736 for p in $allpkgs ; do 1737 # FIXME current version not available 1738 pkgname=`rpm -qp --qf "%{NAME}" $p` 1739 pkgname=${pkgname//[^a-zA-Z0-9_]/_} 1740 oldpkg=pkg_$p 1741 currentversion=pkg_$pkgname currentversion=(${!currentversion}) 1742 currentversion=${currentversion[0]} 1743 logWrite 0 "Installed $p$test (old version was $currentversion)" 1744 COUNTER[_INST]=$((COUNTER[_INST]+1)) 1745 done 1746 for p in $allpkgs ; do 1747 if [[ $REMOVE -eq 1 ]] ; then 1748 myEcho 1 "Removing ... $p$test" | fmt -$COLUMNS 1749 logWrite 0 "Removed $p$test" 1750 [[ $TESTMODE -eq 0 ]] && rm -f $p 1751 fi 1752 done 1753 if [[ -n $POSTINSTLIST ]] ; then 1754 currentdir=$PWD 1755 cd "$BASEDIR" 1756 POSTINSTLIST=`echo $POSTINSTLIST | sort | uniq` 1757 for j in $POSTINSTLIST ; do 1758 echo -e "$COL_CYAN*** Postinstall information for ${j##*/}:" 1759 lang=$LANGUAGE gnal=$EGAUGNAL 1760 checkLanguage "`awk "/Postinformation.$lang:/,/$gnal.noitamrofnitsop:/" $j`" || { lang=english gnal=Hsilgne ; } 1761 awk "/Postinformation.$lang:/,/$gnal.noitamrofnitsop:/" "$j" | sed '$1;$d' | fmt -$COLUMNS | myRecode 1762 echo -e $COL_NORM 1763 done 1764 POSTINSTLIST= 1765 cd "$currentdir" 1766 fi 1767 myNote 1 "Update successful!" 1768 # run suseconfig only if a pkg was installed, and testmode is not active 1769 [[ $SUSECONFIG -eq 1 ]] && SUSECONFIG=2 1770 rm -f $DESCCACHE $AUTOSKIPPEDPATCHESFILE &>/dev/null #force creation next time 1771 else 1772 echo -e $COL_RED 1773 cat << _EOF 1774 1775 ************************ 1776 * ERROR: Update failed * 1777 ************************ 1778 1779 $rpmresult 1780 1781 _EOF 1782 echo -e $COL_NORM 1783 if [[ $INSTMODE -gt 0 ]] ; then 1784 echo "Please try option --end, -a or --nodeps in case of dependency problems." 1785 echo "Using --nopatchrpms might also help" 1786 else 1787 echo "Please try without option --end, -a or use --nodeps in case of dependency problems." | fmt -$COLUMNS 1788 echo "Using --nopatchrpms might also help" 1789 fi 1790 myError 0 "THE PACKAGES SHOWN ABOVE HAVE NOT BEEN INSTALLED!" 1791 FAILCOUNT=$((FAILCOUNT+count)) 1792 fi 1793 cd "$BASEDIR" 1794 cd "$DLPATH" 1795 } # rpmInstall 1796 1797 1798 ################################ cleanupPackagelist 1799 # Remove old patch description files from currently processed server 1800 function cleanupPackagelist() 1801 { 1802 local slashcount lastpkg i pkg 1803 myEcho 2 "Cleaning up packagelist directory ... " 1804 if [[ $NODOTSUSEVERSION -ge 101 ]] ; then 1805 myWarn 0 "Fixme: Implement cleanupPackagelist for 10.1" 1806 return 1807 fi 1808 local slashcount="$DLPATH/$server/$SERVERPATH/" 1809 slashcount=${slashcount//[^\/]/} 1810 slashcount=${#slashcount} 1811 for i in `ls $DLPATH/$server/$SERVERPATH/$PATCHDIR/*-*([0-9]) 2>/dev/null | sort -t / +$slashcount` ; do 1812 pkg=${i%-*} 1813 pkg=${pkg##*/} 1814 newversion=${i##*-} 1815 myEcho 4 "Cleanup checking $i" 1816 if [[ $lastpkg == $pkg ]] ; then 1817 if [[ $newversion -gt $lastversion ]] ; then 1818 myEcho 2 Cleanup removing $lastfullpkg 1819 rm -f $lastfullpkg 1820 else 1821 myEcho 2 Cleanup removing $i 1822 rm -f $i 1823 i=$lastfullpkg 1824 fi 1825 fi 1826 lastpkg=${i%-*} 1827 lastpkg=${lastpkg##*/} 1828 lastversion=${i##*-} 1829 lastfullpkg=$i 1830 done 1831 } # cleanupPackagelist 1832 1833 1834 ################################ hasGoodSignature 1835 # checks a signature (gpg output) 1836 # Parameters: 1837 # $1: gpg output 1838 # $2: DSA or RSA 1839 # $3: key id 1840 # $4: signer (name + email address) 1841 # $5: builddate (optional) 1842 # returns: buildtime (date of signature) 1843 function hasGoodSignature() 1844 { 1845 local sigresult="$1" buildtime cmp1 cmp2 cmp3=xuxux cmp4=xuxux keyid=$3 1846 if [[ -n $5 ]] ; then 1847 # get time from signature 1848 buildtime=${SIGRESULT##*Signature made } 1849 buildtime=${buildtime%% using $2 key*} 1850 buildtime=`date -d "$buildtime" +%s` 1851 fi 1852 cmp1="*Signature made * using $2 key ID $keyid*" 1853 cmp2="*Good signature from *$4*" 1854 if [[ $RPMVER -eq 40 ]] ; then 1855 keyid=`echo $keyid | tr '[A-Z]' '[a-z]'` 1856 cmp3="*MD5 digest: OK*" 1857 cmp4="*V[34] DSA signature: OK, key ID $keyid*" 1858 elif [[ $RPMVER -ge 48 ]] ; then 1859 keyid=`echo $keyid | tr '[A-Z]' '[a-z]'` 1860 cmp1="*V3 $2 Signature, key ID $keyid: OK*" 1861 cmp2="*Header V3 $2 Signature, key ID $keyid: OK*" 1862 cmp3="*MD5 digest: OK *" 1863 cmp4="*V3 RSA/SHA256 Signature, key ID $keyid: OK*" 1864 elif [[ $RPMVER -ge 44 ]] ; then 1865 keyid=`echo $keyid | tr '[A-Z]' '[a-z]'` 1866 cmp3="*MD5 digest: OK*" 1867 cmp4="*V3 RSA/SHA256 signature: OK, key ID $keyid*" 1868 fi 1869 if [[ $sigresult == $cmp1 && $sigresult == $cmp2 ]] ; then 1870 [[ $5 ]] && RETVAL="$buildtime" 1871 return 0 1872 elif [[ $sigresult == $cmp3 && $sigresult == $cmp4 ]] ; then 1873 [[ $5 ]] && RETVAL="$buildtime" 1874 return 0 1875 elif [[ $sigresult == *no\ valid\ OpenPGP\ data\ found* ]] ; then 1876 RETVAL="$sigresult" 1877 return 254 1878 else 1879 RETVAL="$sigresult" 1880 return 255 # error 1881 fi 1882 } # hasGoodSignature 1883 1884 1885 ################################ hasGoodRpmSignature 1886 # check the signature of an rpm file 1887 # parameter: 1888 # $1 rpm file to check 1889 function hasGoodRpmSignature() 1890 { 1891 local baserpm=$1 1892 sigresult="`rpm -v --checksig $baserpm 2>&1`" 1893 if hasGoodSignature "$sigresult" RSA/SHA256 3dbdc284 "openSUSE Project Signing Key <opensuse@opensuse.org>" ; then 1894 return 0 # ok 1895 elif hasGoodSignature "$sigresult" DSA 9C800ACA "SuSE Package Signing Key <build@suse.de>" ; then 1896 return 0 # ok 1897 elif [[ $pkg == fou4s ]] && hasGoodSignature "$sigresult" DSA $FOU4SKEY "fou4s build key <fou4s@gaugusch.at>" ; then 1898 return 0 # ok 1899 elif [[ $pkg == fou4s ]] && hasGoodSignature "$sigresult" DSA/SHA1 $FOU4SKEY "fou4s build key <fou4s@gaugusch.at>" ; then 1900 return 0 # ok 1901 elif [[ $sigresult == *gpg:\ Good\ signature\ from* ]] && \ 1902 [[ $sigresult != *gpg:\ WARNING:\ This\ key\ is\ not\ certified\ with\ a\ trusted\ signature* ]] ; then 1903 return 0 # ok 1904 elif [[ $sigresult == *V3\ DSA\ signature:\ OK* ]] && \ 1905 [[ $sigresult != *gpg:\ WARNING:\ This\ key\ is\ not\ certified\ with\ a\ trusted\ signature* ]] ; then 1906 return 0 # ok 1907 else 1908 if [[ `echo "$sigresult" | wc -l` -le 2 && $sigresult == *MD5\ sum\ OK* ]] ; then 1909 myError 0 "No signature found in $baserpm! You may want to use -g to ignore this error" | fmt -$COLUMNS 1910 else 1911 myError 0 "Signature verification failed for $baserpm (no installation)! You may want to try the -g option to ignore this error." | fmt -$COLUMNS 1912 myWarn 0 "$sigresult" 1913 fi 1914 echo 1915 return 254 # not ok 1916 fi 1917 } # hasGoodRpmSignature 1918 1919 1920 ################################ padZero 1921 # replaces all consecutive digits with zero padded equivalents of known 1922 # length, all nondigits remain intact: 1923 # 3.0.20 -> 00000003.00000000.00000020 1924 # 3.0.3 -> 00000003.00000000.00000003 1925 # by l.g.e 1926 function padZero() 1927 { 1928 local v="$1" part allzeroes=0000000000 1929 RETVAL=() 1930 while [[ -n $v ]] ; do 1931 part=${v%%[0-9]*} # nondigits 1932 v=${v#$part} 1933 RETVAL=$RETVAL$part 1934 [[ $v ]] || break 1935 part=${v%%[^0-9]*} # digits 1936 v=${v#$part} 1937 part=${allzeroes: ${#part}}$part 1938 RETVAL=$RETVAL$part 1939 done 1940 } # padZero 1941 1942 1943 ################################ vcmp 1944 # version compare version_a op version_b 1945 # op is one of the allowed operators in [ ] 1946 # by l.g.e 1947 function vcmp() 1948 { 1949 local a=$1 op=$2 b=$3 ret bool 1950 padZero $a; a=$RETVAL 1951 padZero $b; b=$RETVAL 1952 1953 [ $a $op $b ] 1954 ret=$? 1955 myEcho 3 "Comparing $a $op $b: $ret " 1956 # if this happens, you called this with an invalid op 1957 # check source code! 1958 [[ $ret -gt 1 ]] && { myError 0 "Error ($ret) in vcmp ($pkg):" [ $a \\$op $b ]; } 1959 1960 # warn to stderr if length of padded a and b differ 1961 # it was something like a=3.0 and b=3.0.1 1962 # or a=0.8.7 and b=0.9.1_beta 1963 if [[ ${#a} != ${#b} && $FORCEINSTALL -eq 0 && $3 != 0.0.0.0-0 && $3 != N/A && $kind != generated ]] && ! packageFiltered $pkg $kind $series; then 1964 if [ $VCMP_OK -eq 0 ] ; then 1965 if [[ "`zypper vcmp 2>&1 | head -1`" == "Required argument missing." ]]; then 1966 myEcho 3 "Tested zypper fallback ok" 1967 VCMP_OK=1 1968 fi 1969 fi 1970 if [[ $VCMP_OK -eq 1 ]] ; then 1971 myEcho 3 "Falling back to zypper vcmp $1 $3" 1972 if [[ `zypper vcmp $1 $3` == *newer* ]] ; then 1973 ret=0 1974 else 1975 ret=1 1976 fi 1977 else 1978 if [[ $QUIET -eq 0 ]] ; then 1979 [[ $ret -eq 1 ]] && bool=false || bool=true 1980 myWarn 2 "Warn: Different version structure: $pkg: $1 $op $3 = $bool" >&2 1981 myWarn 2 "Using buildtime to check again for safety ..." >&2 1982 fi 1983 usebuildtime=1 # non-global variable only used for this check in checkpkg. 1984 ret=1 1985 fi 1986 fi 1987 return $ret 1988 } # vcmp 1989 1990 1991 ################################ packageFiltered 1992 # Returns true, if package should not be processed 1993 # parameters: 1994 # $1: package name 1995 # $2: kind 1996 # $3: series 1997 function packageFiltered() 1998 { 1999 local pkg=$1 kind=$2 series=$3 patchname currenttime 2000 [[ $SECURITY -eq 1 && $kind != security ]] && return 0 2001 [[ $SKIPOPTIONAL -eq 1 && $kind == optional ]] && return 0 2002 [[ $GENERATED -eq 0 && $kind == generated ]] && return 0 2003 currenttime=`date +%s` 2004 if [[ $((newbuildtime+DAYSOLDER*60*60*24)) -gt $currenttime ]] ; then 2005 return 0 2006 fi 2007 [[ $((BUILDTIME+days*60*60*24)) -gt $currenttime ]] && return 0 2008 if [[ -n $EXCLUDELIST ]] ; then 2009 patchname=${i##*/} 2010 if [[ $series == @($EXCLUDELIST) ]] ; then 2011 myEcho 2 "Skipping $pkg with series $series" 2012 return 0 2013 fi 2014 if [[ $patchname == @($EXCLUDELIST) ]] ; then 2015 myEcho 2 "Skipping $pkg in patch description ${i##*/}" 2016 return 0 2017 fi 2018 if [[ $pkg == @($EXCLUDELIST) ]] ; then 2019 myEcho 2 "Skipping $pkg in patch description ${i##*/}" 2020 return 0 2021 fi 2022 if [[ $pkg-$newversion == @($EXCLUDELIST) ]] ; then 2023 myEcho 2 "Skipping $pkg in patch description ${i##*/}" 2024 return 0 2025 fi 2026 fi 2027 if [[ -n $IGNORELIST ]] && 2028 [[ $pkg-$newversion == @($IGNORELIST) || $pkg == @($IGNORELIST) ]] 2029 then 2030 # quiet and verbose are both set in automode! 2031 # but we don't want ignore messages there 2032 [[ $QUIET -eq 0 ]] && \ 2033 myNote 1 "\nIgnoring $pkg (matches config file directive $IGNORELIST)" 2034 return 0 2035 fi 2036 if [[ $pkg-$newversion == @($REMARKLIST) || $pkg == @($REMARKLIST) ]] ; then 2037 remarkonly=1 2038 myEcho 2 "Remark only: $pkg" 2039 fi 2040 if [[ $ONLYINSTALLEDUSERRPMS -eq 1 ]] ; then 2041 [[ $pkg == @($USERRPMS) ]] || return 0 2042 [[ $currentversion == N/A && $kind != script && $GETALL -eq 0 ]] && return 0 2043 fi 2044 return 1 # package was not filtered 2045 } # packageFiltered 2046 2047 2048 ################################ guessVersionFromFilename 2049 # expects $rpm (=path/name-ver-rel.somthing.rpm) in the environment, 2050 # splits it up into its components 2051 # modifies environment: 2052 # newversion = ver-rel 2053 # pkg = name 2054 # series = path components after first SUSEVERSION/ 2055 function guessVersionFromFilename () 2056 { 2057 local rel ver path=${rpm#*$SUSEVERSION/} 2058 while true; do # kind of exception handling :) 2059 pkg=${path##*/} 2060 series=${path%/*}; 2061 [[ $series == $path ]] && series="unknown" 2062 rel=${pkg##*-} 2063 [[ $rel != $pkg && $rel == [0-9]* ]] || break #no '-' found 2064 rel=${rel%%.*} 2065 pkg=${pkg%-*} 2066 ver=${pkg##*-} 2067 [[ $ver == $pkg ]] && break # no second '-' found 2068 pkg=${pkg%-*} 2069 newversion="$ver-$rel" 2070 return 0 2071 done 2072 # only reached on error 2073 pkg=${pkg%%.*} 2074 return 1 2075 } # guessVersionFromFilename 2076 2077 2078 ################################# checkPreInstallInfo 2079 # Handles preinstall information for the user 2080 # parameters: 2081 # $1: package name 2082 # $2: patch description file containing pre install info 2083 function checkPreInstallInfo() 2084 { 2085 local pkg=$1 pkgdescfile=$2 currentdir answer lang gnal 2086 if [[ $PREINFO -eq 1 && $INTERACTIVE -eq 1 ]] ; then 2087 myNote 0 "Package $pkg contains the following pre-install (license) information:" 2088 currentdir=$PWD 2089 cd "$BASEDIR" 2090 cd "$DLPATH" 2091 lang=$LANGUAGE gnal=$EGAUGNAL 2092 echo -en "$COL_WHITE" 2093 if [[ $NODOTSUSEVERSION -lt 101 ]] ; then 2094 checkLanguage "`awk "/Preinformation.$lang:/,/$gnal.noitamrofnierp:/" $pkgdescfile`" || { lang=english gnal=Hsilgne ; } 2095 awk "/Preinformation.$lang:/,/$gnal.noitamrofnierp:/" $pkgdescfile | grep -v -F "Preinformation.$lang" | grep -v -F "$gnal.noitamrofnierp" | fmt -$COLUMNS 2096 else 2097 echo "$license" | myRecode | fmt -$COLUMNS 2098 fi 2099 echo -en "$COL_NORM" 2100 cd "$currentdir" 2101 if [[ $ACCEPTPREINSTALLINFO -eq 0 ]] ; then 2102 myRead "Perform update (yes/no)? " <&6 2103 [[ $answer != y ]] && return 1 2104 fi 2105 fi 2106 return 0 2107 } # checkPreInstallInfo 2108 2109 2110 ################################# getUserChoice 2111 # ask user to perform download/update 2112 # returns false if not updating, else true 2113 function getUserChoice() 2114 { 2115 local ok=0 v descr 2116 if [[ $INTERACTIVE -eq 1 ]] ; then 2117 [[ $DOINSTALL -eq 1 ]] && upd="/update" 2118 while [ $ok -ne 1 ] ; do 2119 [[ $VERBOSE -lt 1 ]] && descr="/show [D]escription" || descr= 2120 myRead "Perform download$upd ([Y]es/[N]o/[S]kip forever$descr)? [$LASTANSWER] " <&6 2121 case "$answer" in 2122 y) 2123 ok=1 ;; 2124 n) 2125 ok=1 ;; 2126 s) 2127 ok=1 ;; 2128 d|D) 2129 v=$VERBOSE 2130 VERBOSE=1 2131 printUpdateInformation $i "$shortdesc" 2132 VERBOSE=$v 2133 ;; 2134 V) 2135 if [[ $VERBOSE -lt 4 ]] ; then 2136 VERBOSE=$((VERBOSE+1)) 2137 echo Verbosity increased to $VERBOSE 2138 fi ;; 2139 v) 2140 if [[ $VERBOSE -gt 0 ]] ; then 2141 VERBOSE=$((VERBOSE-1)) 2142 echo Verbosity decreased to $VERBOSE 2143 fi ;; 2144 "") 2145 answer=$LASTANSWER 2146 ok=1 ;; 2147 *) 2148 echo "Wrong input! Use y/n/s or return for last choice. Change verbosity +/- with V/v." 2149 esac 2150 done 2151 LASTANSWER=$answer 2152 if [[ $answer == s ]] ; then 2153 myEcho 0 "${COL_YELLOW}Skipping $COL_RED$pkg-$newversion$COL_YELLOW forever ... $COL_NORM(look at skipped-patches file to enable again)" | fmt -$COLUMNS 2154 if [[ $NODOTSUSEVERSION -lt 110 ]] ; then 2155 addToSkippedPatches "`basename $i`" 2156 else 2157 addToSkippedPatches "$pkg-$newversion" 2158 fi 2159 return 1 2160 fi 2161 if [[ $answer != y ]] ; then 2162 myNote 0 "Skipping $pkg from $patchfile ..." 2163 return 1 2164 fi 2165 fi 2166 return 0 2167 } # getUserChoice 2168 2169 2170 ################################# getRpm 2171 # downloads a package if user permits (in interactive mode) 2172 # parameters: 2173 # $1: name of patch (for printing) 2174 # $2: rpm file to download 2175 # $3: size of rpm 2176 # $4: URL to download 2177 # return value: true if download went ok 2178 function getRpm() 2179 { 2180 local rpm=$1 pkg=$2 size=$3 dlfile=$4 wgetopts="-q" rsyncopts="-q --progress" 2181 [[ $VERBOSE -ge 1 ]] && wgetopts="" && rsyncopts="--progress -v" 2182 cd "$BASEDIR" 2183 cd "$DLPATH" 2184 if fileExists $server $rpm && [ $FOUNDSIZE -eq $size ] ; then 2185 myWarn 2 "Skipping download of $pkg - already complete" 2186 return 0 2187 fi 2188 [[ $kind == script ]] && fileExists $server $rpm && return 0 2189 cd "$server/$SERVERPATH" 2190 [[ ! -d $rpmpath ]] && mkdir -p $rpmpath 2191 cd "$rpmpath" 2192 if [[ $DOWNLOAD -eq 1 ]] ; then 2193 if [[ $origurl == *://* ]] ; then 2194 [[ $QUIET -eq 0 ]] && myNote 0 "Getting $origurl" 2195 else 2196 [[ $QUIET -eq 0 ]] && myNote 0 "Getting $server:$rpm" 2197 fi 2198 if [[ $dlfile == rsync://* ]] ; then 2199 rsync $RSYNCOPTS $rsyncopts "$dlfile" . 2200 ret=$? 2201 [[ $ret -eq 20 ]] && exit 8 # handle ctrl-c 2202 else 2203 getremotefile -b -c $AUTHOPTS $wgetopts "$dlfile" 2204 ret=$? 2205 fi 2206 if [[ ! -f ${rpm##*/} ]] ; then # only abort if file doesn't exist 2207 [[ $ret -ne 0 ]] && myError 0 "Error getting $server:$rpm: $ret" 2208 cd "$BASEDIR" 2209 cd "$DLPATH" 2210 return 1 # error 2211 fi 2212 2213 if [[ $USEDELTARPMS -eq 1 ]] ; then 2214 rpmname=`basename $rpm` 2215 if [[ $rpmname == *.delta.rpm || $rpmname == *.drpm ]] ; then 2216 newrpmname=${rpmname%%.delta.rpm} 2217 newrpmname=${rpmname%%.drpm} 2218 applydeltarpm $rpmname $newrpmname.rpm 2219 fi 2220 fi 2221 fi 2222 cd "$BASEDIR" 2223 cd "$DLPATH" 2224 return 0 # ok 2225 } # getRpm 2226 2227 2228 ################################# processDownloadedRpm 2229 # checks the downloaded rpm signature, version and installs it 2230 # parameters: 2231 # $1: package name 2232 # $2: rpm file name 2233 # $3: new version 2234 # $4: short filename (without path) 2235 function processDownloadedRpm() 2236 { 2237 local pkg=$1 rpm=$2 newversion=$3 baserpm=$4 2238 cd "$BASEDIR" 2239 cd "$DLPATH" 2240 cd "${FOUNDFILE%/*}" # directory where file was found 2241 if [[ $AUTOMODE -eq 1 ]] && [[ -z $pkg || $pkg != @($AUTOLIST) ]]; then 2242 # package not in autolist 2243 cd "$BASEDIR" 2244 return 2245 fi 2246 2247 if [[ $SKIPGPG -eq 0 ]] ; then 2248 hasGoodRpmSignature $baserpm || { FAILCOUNT=$((FAILCOUNT+1));return; } 2249 fi 2250 2251 # check version of downloaded rpm again - it may be different 2252 dlrpminfo=(`rpm -qp $baserpm --queryformat "%{VERSION}-%{RELEASE} %{ARCH}" 2>/dev/null`) 2253 newpkgver=${dlrpminfo[0]} 2254 newrpmarch=${dlrpminfo[1]} 2255 ok=0 2256 for a in $VALIDARCHS ; do 2257 [[ $a == $newrpmarch ]] && ok=1 && break 2258 done 2259 [[ $ok -eq 0 ]] && myWarn 0 "Bad arch for $pkg: $newrpmarch, skipping" && return 2260 if [[ $newpkgver != $newversion && $currentversion != N/A ]] ; then 2261 myWarn 0 "Warning: Downloaded RPM has version $newpkgver, but patch description says $newversion!" 2262 if [[ $newpkgver != $currentversion ]] ; then 2263 # compare with version 2264 if vcmp "$newpkgver" \> "$currentversion" ; then 2265 echo "Using $baserpm $newpkgver anyway" 2266 else 2267 myWarn 0 "Not installing $baserpm (same or newer version already installed)." 2268 return 2269 fi 2270 else 2271 myNote 0 "Same $baserpm already installed (no installation)." 2272 return 2273 fi 2274 fi 2275 2276 # if pre install info is there, we can't continue (except for interactive m.) 2277 checkPreInstallInfo $pkg $i || return 2278 2279 if [[ $baserpm == *.delta.rpm || $baserpm == *.drpm ]] ; then 2280 myEcho 1 "Applying delta RPM for $pkg ..." 2281 [[ ! -f ${baserpm%%.delta.rpm}.rpm ]] \ 2282 && applydeltarpm $baserpm ${baserpm%%.delta.rpm}.rpm 2283 FOUNDFILE=${FOUNDFILE%%.delta.rpm}.rpm 2284 baserpm=$FOUNDFILE 2285 hasGoodRpmSignature $baserpm || { FAILCOUNT=$((FAILCOUNT+1));return; } 2286 fi 2287 2288 if [[ $INSTMODE -gt 0 ]] ; then 2289 RPMINSTLIST="$RPMINSTLIST $FOUNDFILE" 2290 if [[ $POSTINFO -eq 1 ]] ; then # show post installation info for 2291 POSTINSTLIST="$POSTINSTLIST $i" # this package 2292 POSTINFO=0 2293 fi 2294 else 2295 #fixme old version is not available! 2296 logWrite 1 "Going to install $pkg $newversion [$kind]$test" 2297 rpmInstall $baserpm 2298 fi 2299 cd "$BASEDIR" 2300 cd "$DLPATH" 2301 } # processDownloadedRpm 2302 2303 2304 ################################# processScript 2305 # processes an install script 2306 # parameters: 2307 # $1: script name 2308 function processScript() 2309 { 2310 local pkg=$1 fullname=$DLPATH/$server/$SERVERPATH/scripts/$pkg 2311 TMPFILE=$CACHEDIR/$pkg.$PPID 2312 2313 [[ -e $TMPFILE ]] && rm -f $TMPFILE 2314 if hasGoodSignature "`gpg --no-tty -o "$TMPFILE" --decrypt "$fullname" 2>&1`" \ 2315 DSA 9C800ACA "SuSE Package Signing Key <build@suse.de>" ; then 2316 2317 # if pre install info is there, we can't continue (except for interactive m.) 2318 checkPreInstallInfo $pkg $i || return 2319 2320 if [[ -n $EXPORTFILE && $EXPORT -eq 1 ]] ; then 2321 addToRpmExportList $fullname 2322 return 0 2323 fi 2324 logWrite 1 "Going to install $pkg $newversion [$kind]$test" 2325 chmod +x "$TMPFILE" 2326 myNote 0 "Executing script $pkg ..." 2327 if [[ $TESTMODE -eq 0 ]] ; then 2328 $TMPFILE 2329 ret=$? 2330 myEcho 0 "Script finished with code $ret" 2331 if [[ $ret -eq 0 ]] ; then 2332 myEcho 0 "Adding ${i##*/} to skipped-patches" 2333 addToSkippedPatches ${i##*/} 2334 [[ $SUSECONFIG -eq 1 ]] && SUSECONFIG=2 2335 else 2336 myNote 0 "Not adding $pkg to skipped-patches file because of bad return code!" 2337 fi 2338 else 2339 myEcho 0 "... skipped because of testmode" 2340 fi 2341 rm -f $TMPFILE 2342 else 2343 myError 0 "Bad signature in script $pkg!" 2344 rm -f $TMPFILE 2345 return 1 2346 fi 2347 } # processScript 2348 2349 2350 ################################# processXMLScript 2351 # processes an install script from an XML patch description 2352 function processXMLScript() 2353 { 2354 echo "executing script: $scriptcode" | myRecode 2355 } 2356 2357 2358 ################################# fileExists 2359 # checks if a given package has been downloaded. All servers are checked 2360 # and some archs for probing unknown packages 2361 # Parameter: 2362 # $1: primary server to search on 2363 # $2: rpm name with path (a1/bash-2.0.4-4.i586.rpm or i586/bash-2.0.4-4.i586.rpm 2364 function _fileExists() 2365 { 2366 local server=$1 rpm=$2 f arch file a rpmarch 2367 2368 FOUNDFILE=$DLPATH/$server/$SERVERPATH/$rpm 2369 [[ -f $FOUNDFILE ]] && return 0 # that was easy 2370 rpmname=${rpm##*/} 2371 firstpath=${rpm%%/*} 2372 for a in $VALIDARCHS ; do 2373 [[ $rpm == *.$a.rpm ]] && rpmarch=$a && break 2374 done 2375 for f in $DLPATH/*/$SERVERPATH ; do 2376 FOUNDFILE=$f/$rpm 2377 [[ -f $FOUNDFILE ]] && return 0 # that was relatively easy 2378 for a in $VALIDARCHS ; do 2379 FOUNDFILE=$f/$firstpath/$a/${rpmname//$rpmarch/$a} 2380 [[ -f $FOUNDFILE ]] && return 0 # not so easy to find 2381 done 2382 done 2383 FOUNDFILE= 2384 return 1 # not found 2385 } # _fileExists 2386 2387 function fileExists() 2388 { 2389 FOUNDSIZE=0 2390 _fileExists "$@" && FOUNDSIZE=$(find $FOUNDFILE -maxdepth 0 -printf "%s") 2391 } # fileExists 2392 2393 2394 ################################# showPackage 2395 # Shows the given package to the user in a friendly way 2396 # Parameters: 2397 # $1: package name (short) 2398 # $2: new version 2399 # $3: old version 2400 # $4: kind 2401 # $5: size 2402 # $6: series 2403 # $7: remarkonly (0/1) 2404 # Return value: 2405 # Returns false, if the package is on remarklist. checkPackage will exit in that 2406 # case 2407 function showPackage() 2408 { 2409 # local pkg=$pkg.$series # for arch debugging only 2410 #showPackage $pkg $newversion $currentversion $kind $size $series $remarkonly || continue 2411 #local pkg=$1 newversion=$2 currentversion=$3 kind=$4 size=$5 series=$6 2412 #local remarkonly=$7 2413 local ksize=$((size/1024)) ckind # colored version of 'kind' field 2414 local nvsize=13 cvsize=13 # size of version fields in printf 2415 local p=" " rwidth=$RWIDTH 2416 if [[ $VERBOSE -ge 2 ]] ; then 2417 [[ $rpm == *.delta.rpm || $rpm == *.drpm ]] && p="*" 2418 [[ $rpm == *.patch.rpm ]] && p="+" 2419 fi 2420 if fileExists $server $rpm ; then 2421 [[ $kind == script ]] && FOUNDSIZE=$size 2422 [[ $FOUNDSIZE == $size ]] \ 2423 && dl="$COL_GREEN[ok]$COL_NORM" \ 2424 || dl="$COL_YELLOW[d?]$COL_NORM" 2425 else 2426 dl="$COL_RED[dl]$COL_NORM" 2427 fi 2428 if [[ -n $COL_NORM ]] ; then # color support 2429 [[ $kind = security ]] && ckind="$COL_RED" 2430 [[ $kind = recommended ]] && ckind="$COL_CYAN" 2431 fi 2432 [[ ${#newversion} -ge 13 ]] && z=${#newversion} && cvsize=$((13-(z-13))) 2433 [[ ${#currentversion} -ge 13 ]] && z=${#currentversion} && nvsize=$((13-(z-13))) 2434 nvs=${#newversion} 2435 cvs=${#currentversion} 2436 [[ $((nvs+cvs)) -gt 26 ]] && z=$((nvs+cvs)) && rwidth=$((RWIDTH-(z-26) )) 2437 [[ $updateinfoshown -eq 0 ]] && printUpdateInformation $i "$shortdesc" && updateinfoshown=1 2438 printf "$COL_WHITE%-"$rwidth"b $COL_GREEN%-"$nvsize"b$COL_NORM (%b%-"$cvsize"b%b)$p$dl $ckind%-12b$COL_NORM%5bkb \n" "$pkg" "$newversion" "$COL_RED" "$currentversion" "$COL_NORM" "$kind" "$ksize" 2439 [[ $size = 0 && $series != script ]] && \ 2440 myWarn 1 "Warning: $pkg: Invalid size in patch description: 0!" 2441 if [[ $remarkonly -eq 1 && $INTERACTIVE -eq 0 ]] ; then 2442 echo "($pkg will not be updated because of RemarkList entry)" 2443 return 1 2444 fi 2445 2446 if [[ $INTERACTIVE -eq 0 && $EXPORT -eq 0 ]] ; then 2447 if [[ $series == script ]] ; then 2448 myWarn 0 "NOTE: Script must be installed using$COL_CYAN fou4s -i --interactive:$COL_YELLOW $pkg" 2449 elif [[ $PREINFO -eq 1 ]] ; then 2450 myNote 0 "NOTE: Package $pkg contains pre-install information." 2451 if [[ $ACCEPTPREINSTALLINFO -eq 0 ]] ; then 2452 myNote 0 "You must install it using$COL_YELLOW fou4s -i --interactive or --acceptpreinstallinfo" 2453 fi 2454 fi 2455 fi 2456 return 0 2457 } # ShowPackage 2458 2459 2460 ################################# checkPackage 2461 # processes one RPM file 2462 # parameters: 2463 # $1: package name 2464 # $2: path of rpm on ftp server 2465 # $3: new version 2466 # $4: kind of package 2467 # $5: download size of normal rpm 2468 # $6: download size of patch rpm 2469 # $7: buildtime of package 2470 # $8: series of package (optional) 2471 # $9: filename field of patch description 2472 # $10: short description 2473 function checkPackage() 2474 { 2475 #local pkg=$1 rpm=$2 newversion=$3 kind=$4 size=$5 patchsize=$6 2476 #local newbuildtime=$7 series=$8 filename=$9 shortdesc=${10} 2477 local usepatchrpmnow=0 currentversion="N/A" arch curbuildtime=0 remarkonly=0 2478 local founduserrpm=0 update=0 cacheinfo oldhdsize=0 usedeltarpmnow=0 2479 2480 ALLCOUNT=$((ALLCOUNT+1)) # used for progress bar 2481 [[ $USEPROGRESS -eq 1 ]] && showProgress $ALLCOUNT $MAXCOUNT 2482 2483 # if patchsize is given, we will try to use it 2484 [[ $patchsize -gt 0 ]] && usepatchrpmnow=1 2485 [[ $deltasize -gt 0 ]] && usedeltarpmnow=1 2486 2487 if [[ -z $pkg ]] ; then 2488 myError 0 "Error, no package name, skipping ($# args)" 2489 return 255 2490 fi 2491 if [[ $rpm != *.rpm && $NODOTSUSEVERSION -lt 81 && -z $SUSEPRODUCT ]] ; then 2492 myError 0 "Error, invalid filename in $pkg (${i##*/}), skipping" 2493 return 255 2494 fi 2495 2496 if [[ $newversion == fix-me ]] ; then 2497 myWarn 0 "WARNING: No version in $pkg! Trying to construct version number from filename '${rpm##*/}' ..." | fmt -$COLUMNS 2498 if ! guessVersionFromFilename ; then 2499 myError 0 "ERROR No version found in filename! Skipping ..." 2500 return 2501 fi 2502 echo "Using $pkg $newversion from filename ..." 2503 fi 2504 2505 myNote 2 "Checking $pkg: $newversion [$kind, ${size}b]" 2506 2507 if [[ $NODOTSUSEVERSION -lt 110 ]] ; then 2508 # don't ask me why ... 2509 filename=${filename%%.rpm} 2510 fi 2511 r=${pkg//[^a-zA-Z0-9_]/_} alreadyfound=packageinfo_$r alreadyfound=(${!alreadyfound}) 2512 if [[ $founduserrpm -eq 0 ]] ; then 2513 cacheinfo=pkg_${pkg//[^a-zA-Z0-9_]/_} cacheinfo=${!cacheinfo} 2514 #fixme check the following if $pkg is already on the system 2515 if [[ $pkg.rpm == @($USERRPMS) || $pkg == @($USERRPMS) ]] ; then 2516 founduserrpm=1 currentversion=0.0.0.0-0 usepatchrpmnow=0 2517 if [[ $NODOTSUSEVERSION -lt 101 ]] ; then 2518 arch=`grep "^=Pkg: $pkg " $PACKAGES81 | grep -v src$` 2519 arch=${arch##* } 2520 fi 2521 if [[ -z $arch ]] ; then 2522 for a in $VALIDARCHS ; do 2523 [[ $rpm == *.$a.rpm ]] && arch=$a && break 2524 done 2525 fi 2526 myEcho 3 "Using arch '$arch' for $pkg ($rpm)" 2527 elif [[ $FORCEINSTALL -eq 0 && -z $cacheinfo && $GETALL -eq 0 ]] ; then 2528 PENDINGARRAY[$PENDINGCOUNT]="$*" 2529 PENDINGCOUNT=$((PENDINGCOUNT+1)) 2530 myEcho 3 "Added $pkg to pending list" 2531 return # no forced install - add to pending list 2532 fi 2533 if [[ -z $cacheinfo ]] ; then # forced installation 2534 # disable use of patch rpms if no installed package is found 2535 currentversion="N/A" usepatchrpmnow=0 2536 else 2537 cacheinfo=($cacheinfo) # convert to array 2538 currentversion=${cacheinfo[0]} 2539 curbuildtime=${cacheinfo[1]} 2540 arch=${cacheinfo[2]} 2541 oldhdsize=${cacheinfo[3]} 2542 if [[ $usepatchrpmnow -eq 1 ]] ; then # check PatchRpmBasedOn list 2543 [[ -n $patchbase ]] && usepatchrpmnow=0 && for p in $patchbase ; do 2544 if [[ $p = $currentversion ]] ; then 2545 usepatchrpmnow=1 2546 break 2547 fi 2548 done 2549 [[ -z $patchbase ]] && usepatchrpmnow=1 2550 fi # use patch rpm 2551 fi # empty currentversion 2552 fi # ! GETALL 2553 if [[ -z $arch && $NODOTSUSEVERSION -lt 101 ]] ; then 2554 arch=`grep "^=Pkg: $pkg " $PACKAGES81 | grep -v src$` 2555 arch=${arch##* } 2556 fi 2557 if [[ $NODOTSUSEVERSION -lt 110 ]] ; then 2558 [[ $series != default && $series == @(${VALIDARCHS// /|}) ]] && myEcho 2 "Using arch $series instead of $arch for $pkg" && arch=$series # fixme does this really work?!?! 2559 fi 2560 if [[ $NODOTSUSEVERSION -ge 110 ]] ; then 2561 [[ $series != $arch ]] && myEcho 2 "Arch $series for $pkg does not match original arch $arch" && return 2562 fi 2563 if [[ $filename != *.rpm ]] ; then 2564 if [[ $usepatchrpmnow -eq 1 ]] ; then 2565 filename=$filename-$newversion.$arch.patch.rpm 2566 else 2567 filename=$filename-$newversion.$arch.rpm 2568 fi 2569 myEcho 3 "Found incomplete filename $filename" 2570 fi 2571 if [[ $rpm == unknown ]] || [[ -z $rpm ]] ; then 2572 if [[ -z $arch && $NODOTSUSEVERSION -lt 101 ]] ; then 2573 arch=`grep "^=Pkg: $pkg " $PACKAGES81 | grep -v src$` 2574 arch=${arch##* } 2575 fi 2576 if [[ -z $arch ]] ; then 2577 arch=`rpm -q $pkg --queryformat "%{ARCH}" 2>/dev/null` 2578 fi 2579 if [[ -z $arch && $series != script ]] ; then 2580 myError 0 "\nError: No arch for $pkg!! Fou4s can't install this package ($rpm, $i)" 2581 # FIXME try short name and guess arch 2582 return 2583 fi 2584 rpm=rpm/$arch/$filename 2585 fi 2586 quit=1 2587 [[ $kind == script ]] && quit=0 2588 2589 for a in $VALIDARCHS ; do 2590 [[ $arch == $a ]] && quit=0 && break 2591 done 2592 [[ $quit -eq 1 ]] && myWarn 2 "Invalid arch for $pkg: $arch, skipping" && return 2593 # fixme - does this work? 2594 if [[ $USEFULLPATH -eq 0 || $rpm == *tp://* ]] ; then 2595 baserpm=${rpm##*/} rpmpath=. 2596 else 2597 baserpm=${rpm##*/} rpmpath=${rpm%/*} 2598 rpmpath=${rpmpath##+(/)} # strip leading slashes 2599 rpmpath=${rpmpath##*..+(/)} # some/ugly/../../crappy/../..///path -> path 2600 #rpm="$rpmpath/$baserpm" # build again without ../../crappy//things 2601 fi 2602 [[ $GETALL -eq 1 && $GETALLNEW -eq 0 ]] && update=1 # force when getting all 2603 [[ $GETALLNEW -eq 1 && $currentversion == N/A ]] && update=1 # force when getting all 2604 # forced because of installtrigger or updateonlyinstalled=0 2605 [[ $FORCEINSTALL -eq 1 && $remarkonly -eq 0 ]] && update=1 2606 # compare packages 2607 if [[ $update -eq 0 ]] ; then 2608 local usebuildtime=$USEBUILDTIME # can be overwritten in vcmp 2609 if [[ $USEBUILDTIME -eq 0 ]] ; then 2610 [[ $currentversion == $newversion ]] && return # same version 2611 [[ -n $currentversion && $currentversion != N/A ]] && \ 2612 vcmp "$newversion" \> "$currentversion" && update=1 2613 [[ $currentversion == N/A ]] && update=1 2614 fi 2615 if [[ $usebuildtime -eq 1 && $currentversion != N/A ]] ; then 2616 [[ -n $newbuildtime && -n $curbuildtime && \ 2617 $newbuildtime -gt $curbuildtime ]] && update=1 2618 fi 2619 fi 2620 origurl=$rpm 2621 if [[ $rpm == *://* ]] ; then # check for absolute http/ftp links 2622 dlfile=$rpm 2623 else 2624 if [[ $NODOTSUSEVERSION -lt 101 && $SERVERPATH != *$ARCH/update/$SUSEPRODUCT$SUSEVERSION* ]] ; then 2625 dlfile=$SERVERURL/$rpm 2626 elif [[ $NODOTSUSEVERSION -ge 101 && $SERVERPATH != *update/$SUSEPRODUCT$SUSEVERSION* ]] ; then 2627 dlfile=$SERVERURL/$rpm 2628 else 2629 dlfile=$SERVERURL/$SERVERPATH/$rpm 2630 fi 2631 fi 2632 rpm="$rpmpath/$baserpm" # build again without ../../crappy//things 2633 2634 # try to prevent download of one package several times 2635 # for each package we create version_<packagename> variable with the version 2636 # that was found. if this variable exists, tha package has already been found 2637 if [[ -n $alreadyfound ]] ; then 2638 foundarch=packageinfo_$r 2639 foundarch=(${!foundarch}) foundarch=${foundarch[4]} 2640 if [[ $alreadyfound == $newversion ]] ; then 2641 if ! betterArch "$arch" "$foundarch"; then 2642 myWarn 2 "Using ${rpm##*/} as alternative (same version already found)." 2643 eval dlfile1_$r=$dlfile 2644 eval server1_$r=$server 2645 return 2646 fi 2647 fi 2648 if vcmp "$alreadyfound" \> "$newversion" ; then 2649 myWarn 2 "Not processing ${rpm##*/} (newer version already found)." 2650 return 2651 fi 2652 fi 2653 [[ $update -eq 0 ]] && return 2654 p=${pkgdescname//[^a-zA-Z0-9_]/_} 2655 val="$newversion $currentversion $kind $size $series $remarkonly $rpm $dlfile $server $oldhdsize $newhdsize $i $pkgdescname $newbuildtime $PREINFO $sourcerpm $origurl $SERVERPATH $usepatchrpmnow $patchsize $SERVERURL $usedeltarpmnow $deltasize $deltarpm $patchrpm" 2656 eval packageinfo_$r='$val' 2657 eval package_${p}_MG_$r='$pkg' 2658 eval shortdesc_$r='$shortdesc' 2659 eval longdesc_$r='$longdesc' 2660 eval license_$r='$license' 2661 if [[ $UPDATEONLYINSTALLED -eq 0 && $COMPATIBLE -eq 1 && $PENDINGCOUNT -gt 0 ]] ; then 2662 myWarn 3 "Forcing $PENDINGCOUNT pending packages" 2663 FORCEINSTALL=1 2664 count=$((PENDINGCOUNT-1)) # seq command requires this 2665 PENDINGCOUNT=0 # recursion would fail if we leave it to some other value 2666 for args in "${PENDINGARRAY[@]}" ; do 2667 ALLCOUNT=$((ALLCOUNT-1)) # we check again, therefore must decrement 2668 checkPackage $args 2669 done 2670 fi 2671 } # CheckPackage 2672 2673 2674 ################################# handleInstallTrigger 2675 # sets FORCEINSTALL if install trigger returns true (0) 2676 function handleInstallTrigger() 2677 { 2678 if [[ $SAFEPKGDESC -eq 1 ]] ; then # only signed packages! 2679 TMPFILE=`mktemp $CACHEDIR/insttrigger.XXXXXX` 2680 if [[ $? -eq 0 ]] ; then 2681 while read ; do 2682 case "$REPLY" in 2683 Reggirtllatsni:) 2684 break ;; 2685 esac 2686 echo "$REPLY" >> $TMPFILE 2687 done 2688 chmod +x $TMPFILE 2689 $TMPFILE # execute install trigger 2690 if [[ $? -eq 0 ]] ; then 2691 myEcho 3 "Forcing install of $pkg because of installtrigger" 2692 FORCEINSTALL=1 2693 fi 2694 # FIXME what should we do, if install trigger returns false? 2695 # Normal checking or ignoring this package?!?! Currently: normal check 2696 rm -f $TMPFILE 2697 else 2698 myError 0 "Error creating tempfile!! Installtrigger cannot be checked!" 2699 fi 2700 else 2701 myWarn 0 "WARNING: Installtrigger found in unsafe patch desc. ${i##*/} - IGNORING!" 2702 fi 2703 } # handleInstallTrigger 2704 2705 2706 ################################# showRpmSummary 2707 # shows summary of one available rpm package (fou4s -l) 2708 function showRpmSummary 2709 { 2710 if packageFiltered $pkg $kind $series; then 2711 return 2712 fi 2713 if [[ $VERBOSE -ge 1 && $LISTAVAILRPMS -eq 1 ]] && \ 2714 ! packageFiltered $pkg $kind $series; then 2715 [[ $updateinfoshown -eq 0 ]] && printUpdateInformation $i "$shortdesc" && updateinfoshown=1 2716 fi 2717 newhdsize=0 # for correct summary 2718 updateStatistics 2719 size=$((size/1024)) 2720 ckind=$COL_NORM 2721 [[ $kind == security ]] && ckind="$COL_RED" 2722 [[ $kind == recommended ]] && ckind="$COL_CYAN" 2723 printf "$COL_WHITE%-35b $COL_GREEN%-18b $ckind%-14b$COL_NORM %5bkb \n" "$pkg" "$newversion" "$kind" "$size" 2724 } # showRpmSummary 2725 2726 2727 ################################# processXMLDescRPM 2728 # save parsed information from xml description (SuSE 10.1 .. 10.3) to internal 2729 # variables 2730 function processXMLDescRPM() 2731 { 2732 myNote 2 "processing rpm $rpm pkg $pkg version $newversion cat $kind arch $series" 2733 if [[ $LISTAVAILRPMS -eq 1 ]] ; then # only show available rpms 2734 showRpmSummary 2735 else 2736 if [[ $USECACHE -ge 1 ]] ; then 2737 for p in pkg rpm newversion kind size newbuildtime series filename shortdesc patchbase patchsize newhdsize sourcerpm PREINFO POSTINFO UPDATEONLYINSTALLED deltasize deltarpm patchrpm longdesc license scriptcode; do 2738 pkg1=${pkg//[^a-zA-Z0-9_-]/} 2739 echo "$p='${!p//\'/\"}'" >> $cachefile.$pkg1 2740 done 2741 fi 2742 checkPackage 2743 fi 2744 2745 # reset values in case that the next loop will not refill them 2746 series=default rpm=unknown pkg=unknown filename=unknown.rpm 2747 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 2748 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 2749 deltarpm=unknown patchrpm=unknown 2750 } 2751 2752 2753 ################################# processUpdateinfoRPM 2754 # save parsed information from xml description (SuSE >= 11.0) to internal 2755 # variables 2756 function processUpdateinfoRPM() 2757 { 2758 newversion=$newversion1-$newversion2 2759 myNote 2 "processing updateinfo rpm $filename pkg $pkg version $newversion cat $kind arch $arch in $pkgdescname" 2760 series=$arch 2761 # echo Needing filename $filename from pkg $pkg pkgdescname $pkgdescname kind $kind ver $newversion 2762 data="$" 2763 p="file_${pkg//[^a-zA-Z0-9_]/_}__${newversion//[^a-zA-Z0-9_]/_}__$arch" 2764 # echo "fixme $p -- ${!p}" 2765 primaryinfo=(${!p}) 2766 newversion=${primaryinfo[0]} 2767 size=${primaryinfo[1]} 2768 arch=${primaryinfo[2]} 2769 rpm=${primaryinfo[3]} 2770 server=${primaryinfo[4]} 2771 newhdsize=${primaryinfo[5]} 2772 newbuildtime=${primaryinfo[6]} 2773 p="deltafile_${pkg//[^a-zA-Z0-9_]/_}__${newversion//[^a-zA-Z0-9_]/_}__$arch" 2774 deltainfo=(${!p}) 2775 deltasize=${deltainfo[0]} 2776 deltarpm=${deltainfo[1]} 2777 i=$pkgdescname 2778 2779 if [[ $LISTAVAILRPMS -eq 1 ]] ; then # only show available rpms 2780 showRpmSummary 2781 else 2782 if [[ $USECACHE -ge 1 ]] ; then 2783 pkg1=${pkg//[^a-zA-Z0-9_-]/} 2784 for p in pkg rpm newversion kind size newbuildtime series filename shortdesc patchbase patchsize newhdsize sourcerpm PREINFO POSTINFO UPDATEONLYINSTALLED deltasize deltarpm patchrpm longdesc license scriptcode pkgdescname i; do 2785 echo "$p='${!p//\'/\"}'" >> $cachefile.$pkgdescname.$pkg1.$series 2786 done 2787 fi 2788 checkPackage 2789 fi 2790 2791 # reset values in case that the next loop will not refill them 2792 series=default rpm=unknown pkg=unknown filename=unknown.rpm 2793 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 2794 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 2795 deltarpm=unknown patchrpm=unknown PREINFO=0 2796 } 2797 2798 2799 ################################# processdeltainfoRPM 2800 # save parsed information from delta xml description (SuSE >= 11.0) to internal 2801 # variables 2802 function processdeltainfoRPM() 2803 { 2804 newversion="$newversion1-$newversion2" 2805 myNote 2 "processing delta rpm $deltarpm pkg $pkg version $newversion arch $deltaarch deltarpm $deltarpm" 2806 2807 p=${pkg//[^a-zA-Z0-9_]/_}__${newversion//[^a-zA-Z0-9_]/_}__$deltaarch 2808 val="$deltasize $deltarpm" 2809 eval deltafile_$p='$val' 2810 2811 # reset values in case that the next loop will not refill them 2812 series=default rpm=unknown pkg=unknown filename=unknown.rpm 2813 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 2814 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 2815 deltarpm=unknown patchrpm=unknown 2816 } 2817 2818 2819 ################################# processPrimaryRPM 2820 # save parsed information from xml description (SuSE >= 11.0) to internal 2821 # variables 2822 function processPrimaryRPM() 2823 { 2824 myNote 2 "processing primary rpm $rpm pkg $pkg version $newversion arch $series" 2825 2826 p=${primaryfilename//[^a-zA-Z0-9_]/_}__${newversion//[^a-zA-Z0-9_]/_}__$arch 2827 val="$newversion $size $arch $rpm $server $newhdsize $newbuildtime $SERVERPATH $SERVERURL" 2828 eval file_$p='$val' 2829 echo "file_$p='$val'" >> $cachefile.tmp 2830 2831 # reset values in case that the next loop will not refill them 2832 series=default rpm=unknown pkg=unknown filename=unknown.rpm 2833 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 2834 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 2835 deltarpm=unknown patchrpm=unknown 2836 } 2837 ################################# processPrimaryXML 2838 # cycle through primary.xml, updateinfo.xml and deltainfo.xml from openSUSE 11.0 and newer 2839 function processPrimaryXML() 2840 { 2841 local rpm pkg newversion size newbuildtime filename patchbase patchsize 2842 local sourcerpm readingPkg series updateinfoshown shortdesc newhdsize kind 2843 local POSTINFO PREINFO FORCEINSTALL PENDINGCOUNT PENDINGARRAY 2844 local UPDATEONLYINSTALLED SAFEPKGDESC i deltasize deltarpm first longdesc 2845 local patchrpm license scriptcode 2846 2847 myEcho 2 "Checking package information on $server" 2848 if [[ ! -f primary.xml.gz || ! -f updateinfo.xml.gz ]] ; then 2849 myWarn 0 "Description files (primary/deltainfo/updateinfo) are not complete for $server" 2850 return 1 2851 fi 2852 [[ $USEPROGRESS -eq 1 ]] && MAXCOUNT=`zgrep "<name>" primary.xml.gz 2>/dev/null| wc -l` 2853 [[ $MAXCOUNT == 0 ]] && MAXCOUNT=1 # otherwise div/0 would occur ... 2854 ALLCOUNT=0 # reset progress bar 2855 myNote 2 "########## Processing primary.xml on $server" 2856 # [[ ! -f $i ]] && myWarn 2 "Missing patch description $i" && continue 2857 cachefile=$CACHEDIR/.cache.$HOSTNAME/primary.$LANGUAGE.$server 2858 newbuildtime=0 2859 pkgdescname=UNKNOWN 2860 rpm=unknown pkg=unknown newversion=0.0-0 size=0 newbuildtime=0 newhdsize=0 2861 filename=unknown.rpm patchbase= patchsize=0 sourcerpm=unknown oldhdsize=0 2862 kind=unknown 2863 readingPkg=0 #currently (not) reading a package info from the pkgdesc file 2864 series=default # initialisation to sane defaults 2865 updateinfoshown=0 # indicates if update information has been shown 2866 shortdesc= # short description 2867 POSTINFO=0 # postinstall information present? 2868 FORCEINSTALL=0 # force installation because of installtrigger 2869 PREINFO=0 PENDINGCOUNT=0 PENDINGARRAY=() 2870 UPDATEONLYINSTALLED=1 # default!! 2871 SAFEPKGDESC=$SKIPGPG # use default from disable gpg option 2872 deltarpm=unknown deltasize=0 first=1 longdesc= patchrpm=unknown license= 2873 deltasize1= deltabaserel= deltabasever= currentversion= deltaseqinfo= 2874 scriptcode= deltachecksum=0 2875 i=UNK 2876 2877 if [[ $DESCCACHE -nt primary.xml.gz && $DESCCACHE -nt deltainfo.xml.gz && $DESCCACHE -nt updateinfo.xml.gz ]] ; then 2878 myEcho 2 "Skipping server $server" 2879 return 0 2880 fi 2881 if [[ $USECACHE -ge 1 && -f $cachefile && $cachefile -nt primary.xml.gz ]] ; then 2882 myEcho 2 "Reading primary xml cache $cachefile ($server)" 2883 source $cachefile 2884 else 2885 xmlparsed=`mktemp $CACHEDIR/.cache.$HOSTNAME/xmlprim.XXXXXXXX` 2886 finished=0 2887 { 2888 zcat primary.xml.gz | $XMLP > $xmlparsed 2889 #xmlpcount=`wc -l < $xmlparsed` 2890 #MAXCOUNT=$((MAXCOUNT+xmlpcount)) 2891 myEcho 2 "Reading primary.xml" 2892 while read line ; do 2893 # does not work because it is inside a subshell 2894 ##[[ $USEPROGRESS -eq 1 ]] && showProgress $ALLCOUNT $MAXCOUNT 2895 ##ALLCOUNT=$((ALLCOUNT+1)) 2896 line=${line//\/metadata\/package\//} 2897 if [[ $line == /metadata/package ]] ; then 2898 if [[ $first -eq 0 && readingPkg -eq 1 ]] ; then 2899 processPrimaryRPM 2900 else 2901 first=0 2902 fi 2903 newbuildtime=0 2904 rpm=unknown pkg=unknown newversion=0.0-0 size=0 newbuildtime=0 newhdsize=0 2905 filename=unknown.rpm 2906 series=default # initialisation to sane defaults 2907 readingPkg=1 2908 fi 2909 [[ $first -eq 0 && $readingPkg -eq 0 ]] && continue 2910 2911 case $line in 2912 arch=*) 2913 series="${line##*=}" 2914 arch=$series 2915 [[ -n $series && $series != default && $series != @(${VALIDARCHS// /|}) ]] && readingPkg=0 && myEcho 3 Ignoring package $pkg with foreign arch $series 2916 ;; 2917 location/@href=*) 2918 rpm=${line##*=} ;; 2919 name=*) 2920 pkg=${line##*=} 2921 primaryfilename="${line##*=}" 2922 filename=$pkg.rpm ;; 2923 version/@ver=*) 2924 newversion=${line##*=} ;; 2925 version/@rel=*) 2926 newversion=$newversion-${line##*=} ;; 2927 size/@package=*) 2928 size=${line##*=} ;; 2929 size/@installed=*) 2930 newhdsize=${line##*=} ;; 2931 time/@build=*) 2932 newbuildtime=${line##*=} ;; 2933 esac 2934 done < $xmlparsed 2935 if [[ $readingPkg -eq 1 ]] ; then 2936 processPrimaryRPM 2937 fi 2938 rm -f $xmlparsed 2939 }& 2940 if [[ $THREADS -eq 0 ]] ; then 2941 wait 2942 fi 2943 fi 2944 if [[ $USECACHE -ge 1 && $cachefile -nt deltainfo.xml.gz ]] ; then 2945 myEcho 2 "Reading deltainfo from cache" 2946 # source $cachefile.delta 2947 elif [[ $USEDELTARPMS -eq 1 ]] ; then 2948 myEcho 2 "Reading deltainfo.xml ..." # todo 2 2949 xmlparsed=`mktemp $CACHEDIR/.cache.$HOSTNAME/xmlpdelta.XXXXXXXX` 2950 zcat deltainfo.xml.gz | $XMLP > $xmlparsed 2951 xmldeltacount=`wc -l < $xmlparsed` 2952 MAXCOUNT=$((MAXCOUNT+xmldeltacount)) 2953 readingPkg=0 2954 firstpkg=1 2955 while read line ; do 2956 [[ $USEPROGRESS -eq 1 ]] && [[ $USEPROGRESS -eq 1 ]] && showProgress $ALLCOUNT $MAXCOUNT 2 2957 ALLCOUNT=$((ALLCOUNT+1)) 2958 #line=${line//\/deltainfo\/newpackage\//} 2959 if [[ $line == /deltainfo/newpackage ]]; then 2960 [[ $readingPkg -eq 1 ]] && processdeltainfoRPM 2961 readingPkg=0 2962 firstpkg=0 2963 fi 2964 case $line in 2965 /deltainfo/newpackage/delta) 2966 if [[ $firstpkg == 1 ]] ; then 2967 firstpkg=0 2968 else 2969 # got one RPM from this updateinfo.xml.gz 2970 [[ $readingPkg -eq 1 ]] && processdeltainfoRPM 2971 readingPkg=0 2972 fi 2973 ;; 2974 /deltainfo/newpackage/@version=*) 2975 newversion1="${line##*=}" ;; 2976 /deltainfo/newpackage/@release=*) 2977 newversion2="${line##*=}" ;; 2978 /deltainfo/newpackage/@name=*) 2979 pkg="${line##*=}" ;; 2980 /deltainfo/newpackage/delta/@filename=*|/deltainfo/newpackage/delta/filename=*) 2981 deltarpm1="${line##*=}" ;; 2982 /deltainfo/newpackage/delta/@size=*|/deltainfo/newpackage/delta/size=*) 2983 deltasize1="${line##*=}" ;; 2984 /deltainfo/newpackage/delta/@oldversion=*|delta/@ver=*) 2985 deltabasever=${line##*=} ;; 2986 /deltainfo/newpackage/delta/@oldrelease=*|delta/@rel=*) 2987 deltabaserel=${line##*=} ;; 2988 /deltainfo/newpackage/@arch=*) 2989 deltaarch=${line##*=} ;; 2990 /deltainfo/newpackage/delta/@sequence=*) 2991 deltaseqinfo=`echo "$line" | sed 's/^.deltainfo.newpackage.delta..sequence=//g'` ;; 2992 /deltainfo/newpackage/delta/sequence=*) 2993 deltaseqinfo=`echo "$line" | sed 's/^.deltainfo.newpackage.delta.sequence=//g'` ;; 2994 /deltainfo/newpackage/delta/checksum=*) # dummy usage because it is the last element 2995 deltarpm=unknown 2996 cacheinfo=pkg_${pkg//[^a-zA-Z0-9_]/_} cacheinfo=(${!cacheinfo}) 2997 currentversion=${cacheinfo[0]} 2998 currentarch=${cacheinfo[2]} 2999 3000 if [[ -n $deltaseqinfo && $deltabasever-$deltabaserel == $currentversion && "$deltaarch" == "$currentarch" ]] ; then 3001 myEcho 2 "Checking if delta RPM $deltabasever-$deltabaserel-$deltaarch for $pkg-$currentversion-$currentarch size $deltasize1 works ... $PWD $deltarpm1" 3002 if [[ -f ../${deltarpm1##.delta.rpm}.rpm ]] || applydeltarpm -c -s "$deltaseqinfo" 2>/dev/null ; then 3003 myWarn 3 "Found delta for $pkg: $deltarpm1" 3004 deltachecksum=${line##*=} 3005 deltasize=$deltasize1 3006 deltarpm=$deltarpm1 3007 readingPkg=1 3008 fi 3009 else 3010 deltasize=0 3011 myEcho 2 "NOT Checking if delta RPM $deltabasever-$deltabaserel-$deltaarch for $pkg-$currentversion-$currentarch size $deltasize1 works ..." 3012 fi 3013 ;; 3014 /deltainfo/newpackage/delta/@arch=*) 3015 arch=${line##*=} 3016 readingPkg=1 3017 [[ $arch != @(${VALIDARCHS// /|}) ]] && readingPkg=0 && myEcho 2 Ignoring package $pkg with foreign arch $arch in deltainfo 3018 ;; 3019 esac 3020 done < $xmlparsed 3021 rm -f $xmlparsed 3022 fi 3023 if [[ $readingPkg -eq 1 ]] ; then 3024 processdeltainfoRPM 3025 fi 3026 3027 #if [[ -f $cachefile-1 && $cachefile.1 -nt updateinfo.xml.gz ]] ; then 3028 # fixme check this 3029 if ! [[ $USECACHE -ge 1 && $LISTAVAILRPMS -eq 0 && -f $cachefile-1 \ 3030 && $cachefile-1 -nt updateinfo.xml.gz ]] ; then 3031 myEcho 2 "Reading updateinfo.xml ..." # todo 2 3032 xmlparsed=`mktemp $CACHEDIR/.cache.$HOSTNAME/xmlpu.XXXXXXXX` 3033 zcat updateinfo.xml.gz | $XMLP > $xmlparsed 3034 fi 3035 3036 wait 3037 ALLCOUNT=0 3038 test -f $cachefile.tmp && mv $cachefile.tmp $cachefile 3039 # read cached info from primary.xml 3040 source $cachefile 3041 3042 if [[ $USECACHE -ge 1 && $LISTAVAILRPMS -eq 0 && -f $cachefile-1 \ 3043 && $cachefile-1 -nt updateinfo.xml.gz ]] ; then 3044 myEcho 2 "Reading updateinfo from cache ($server)" 3045 for j in $cachefile.* ; do 3046 test -f $j && source $j || continue 3047 checkPackage 3048 # reset values in case that the next loop will not refill them 3049 series=default rpm=unknown pkg=unknown filename=unknown.rpm 3050 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 3051 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 3052 deltarpm=unknown patchrpm=unknown PREINFO=0 deltachecksum=0 3053 done 3054 else 3055 myEcho 2 "Parsing updateinfo.xml ..." # todo 2 3056 if [ $LISTAVAILRPMS -eq 1 ] ; then 3057 rm -f $cachefile-1 3058 else 3059 touch $cachefile-1 3060 fi 3061 firstpkg=1 3062 firstupdate=1 3063 while read line ; do 3064 line=${line//\/updates\/update\//} 3065 if [[ $line == /updates/update ]] ; then 3066 if [[ $readingPkg -eq 1 ]] ; then 3067 processUpdateinfoRPM 3068 fi 3069 firstupdate=0 3070 firstpkg=1 3071 readingPkg=0 3072 pkgdescname= kind= longdesc= filename= 3073 updateinfoshown=0 3074 fi 3075 # info: 3076 # @version, @type, id, title/@, issued/@date, description 3077 # pkglist/collection/package/@release,@name,@arch,@version,filename= 3078 # echo reading updateinfo line $line 3079 case $line in 3080 @version=*) 3081 pkgdescname="${line##*=}" i=$pkgdescname ;; 3082 @type=*) 3083 kind="${line##*=}" ;; 3084 id=*) 3085 pkg="${line##*=}" 3086 pkgdescname="${line##*=}-$pkgdescname" ;; 3087 description=*) 3088 longdesc=${line##*=} 3089 longdesc=${longdesc%} 3090 longdesc=${longdesc///=} ;; 3091 title=*) 3092 shortdesc=${line##*=} 3093 shortdesc=${shortdesc%} 3094 shortdesc=${shortdesc///=} ;; 3095 pkglist/collection/package) 3096 if [[ $firstpkg == 1 ]] ; then 3097 firstpkg=0 3098 else 3099 # got one RPM from this updateinfo.xml.gz 3100 [[ $readingPkg -eq 1 ]] && processUpdateinfoRPM 3101 fi 3102 ;; 3103 pkglist/collection/package/@version=*) 3104 newversion1="${line##*=}" ;; 3105 pkglist/collection/package/@release=*) 3106 newversion2="${line##*=}" ;; 3107 pkglist/collection/package/@name=*) 3108 pkg="${line##*=}" ;; 3109 pkglist/collection/package/filename=*) 3110 filename="${line##*=}" ;; 3111 pkglist/collection/package/reboot_suggested=*) 3112 line="${line##*=}" 3113 if [[ $line == 1 ]] ; then 3114 PREINFO=1 3115 license="A reboot is suggested after installing this update" 3116 fi 3117 ;; 3118 pkglist/collection/package/@arch=*) 3119 arch=${line##*=} 3120 readingPkg=1 3121 [[ $arch != @(${VALIDARCHS// /|}) ]] && readingPkg=0 && myEcho 2 Ignoring package $pkg with foreign arch $arch in updateinfo $pkgdescname 3122 ;; 3123 *) 3124 #echo "ignoring $line in updateinfo" 3125 ;; 3126 esac 3127 done < $xmlparsed 3128 if [[ $readingPkg -eq 1 ]] ; then 3129 processUpdateinfoRPM 3130 fi 3131 fi 3132 rm -f $xmlparsed 3133 } 3134 3135 ################################# processXMLPatchDescriptions 3136 # cycle through all XML package description files for SUSE 10.1 .. 10.3 3137 # Parameters: 3138 # $*: the patch description files 3139 function processXMLPatchDescriptions() 3140 { 3141 local rpm pkg newversion size newbuildtime filename patchbase patchsize 3142 local sourcerpm readingPkg series updateinfoshown shortdesc newhdsize kind 3143 local POSTINFO PREINFO FORCEINSTALL PENDINGCOUNT PENDINGARRAY 3144 local UPDATEONLYINSTALLED SAFEPKGDESC i deltasize deltarpm first longdesc 3145 local patchrpm license scriptcode 3146 3147 myEcho 2 "Need to check $# package information files on $server" 3148 [[ $# -eq 0 ]] && return 3149 [[ $USEPROGRESS -eq 1 ]] && MAXCOUNT=`grep "<name>" $* 2>/dev/null| wc -l` 3150 [[ $MAXCOUNT == 0 ]] && MAXCOUNT=1 # otherwise div/0 would occur ... 3151 ALLCOUNT=0 # reset progress bar 3152 for i in $* ; do 3153 pkgdescname=${i##*/patch-} 3154 pkgdescname=${pkgdescname%%.xml} 3155 myNote 3 "########## Processing XML patch description $i $pkgdescname" 3156 [[ ! -f $i ]] && myWarn 2 "Missing patch description $i" && continue 3157 cachefile=$CACHEDIR/.cache.$HOSTNAME/$i.$LANGUAGE 3158 newbuildtime=0 3159 rpm=unknown pkg=unknown newversion=0.0-0 size=0 newbuildtime=0 newhdsize=0 3160 filename=unknown.rpm patchbase= patchsize=0 sourcerpm=unknown oldhdsize=0 3161 kind=unknown 3162 readingPkg=0 #currently (not) reading a package info from the pkgdesc file 3163 series=default # initialisation to sane defaults 3164 updateinfoshown=0 # indicates if update information has been shown 3165 shortdesc= # short description 3166 POSTINFO=0 # postinstall information present? 3167 FORCEINSTALL=0 # force installation because of installtrigger 3168 PREINFO=0 PENDINGCOUNT=0 PENDINGARRAY=() 3169 UPDATEONLYINSTALLED=1 # default!! 3170 SAFEPKGDESC=$SKIPGPG # use default from disable gpg option 3171 deltarpm=unknown deltasize=0 first=1 longdesc= patchrpm=unknown license= 3172 deltasize1= deltabaserel= deltabasever= currentversion= deltaseqinfo= 3173 scriptcode= 3174 3175 if [[ $USECACHE -ge 1 ]] ; then 3176 if [[ -f $cachefile && $cachefile -nt $i ]] ; then 3177 for cf in $cachefile.* ; do 3178 if [[ -f $cf ]] ; then 3179 source $cf 3180 if [[ $LISTAVAILRPMS -eq 1 ]] ; then # only show available rpms 3181 showRpmSummary 3182 else 3183 checkPackage 3184 fi 3185 fi 3186 done 3187 continue 3188 fi 3189 mkdir -p ${cachefile%/*} # create directory for cache file 3190 rm -f $cachefile* 3191 touch $cachefile # empty dummy 3192 fi 3193 3194 xmlparsed=`mktemp $CACHEDIR/.cache.$HOSTNAME/xmlp.XXXXXXXX` 3195 $XMLP <$i > $xmlparsed 3196 while read line ; do 3197 line=${line//\/patch\//} 3198 if [[ $line == atoms/package ]] ; then 3199 if [[ $first -eq 0 && readingPkg -eq 1 ]] ; then 3200 processXMLDescRPM 3201 else 3202 first=0 3203 fi 3204 readingPkg=1 3205 fi 3206 [[ $first -eq 0 && $readingPkg -eq 0 ]] && continue 3207 3208 case $line in 3209 atoms/package/arch=*) 3210 series="${line##*=}" 3211 arch=$series 3212 [[ -n $series && $series != default && $series != @(${VALIDARCHS// /|}) ]] && readingPkg=0 && myEcho 2 Ignoring package $pkg with foreign arch $series 3213 ;; 3214 category=*) 3215 kind="${line##*=}" ;; 3216 license-to-confirm=*) 3217 PREINFO=1 ;; 3218 atoms/package/location/@href=*) 3219 rpm=${line##*=} ;; 3220 atoms/package/name=*) 3221 pkg=${line##*=} 3222 filename=$pkg.rpm;; 3223 atoms/package/version/@ver=*) 3224 newversion=${line##*=} ;; 3225 atoms/package/version/@rel=*) 3226 newversion=$newversion-${line##*=} ;; 3227 atoms/package/size/@package=*) 3228 size=${line##*=} ;; 3229 atoms/package/size/@installed=*) 3230 newhdsize=${line##*=} ;; 3231 atoms/package/time/@build=*) 3232 newbuildtime=${line##*=} ;; 3233 description/@lang=en) 3234 read line 3235 [[ $line == /patch/description=* ]] && longdesc=${line##*=} 3236 longdesc=${longdesc%} longdesc=${longdesc///=} 3237 ;; 3238 summary/@lang=en) 3239 read line 3240 [[ $line == /patch/summary=* ]] && shortdesc=${line##*=} ;; 3241 license-to-confirm) 3242 read line 3243 [[ $line == /patch/license-to-confirm=* ]] && PREINFO=1 license=${line##*=} || read line 3244 [[ $line == /patch/license-to-confirm=* ]] && PREINFO=1 license=${line##*=} 3245 ;; 3246 atoms/package/pkgfiles/patchrpm/location/@href=*) 3247 patchrpm=${line##*=} ;; 3248 atoms/package/pkgfiles/patchrpm/size/@package=*) 3249 patchsize=${line##*=} ;; 3250 atoms/package/pkgfiles/patchrpm/base-version/@ver=*) 3251 patchbase=${line##*=} ;; 3252 atoms/package/pkgfiles/patchrpm/base-version/@rel=*) 3253 patchbase=$patchbase-${line##*=} ;; 3254 atoms/package/pkgfiles/deltarpm/location/@href=*) 3255 deltarpm1=${line##*=} ;; 3256 atoms/package/pkgfiles/deltarpm/size/@package=*) 3257 deltasize1=${line##*=} ;; 3258 atoms/package/pkgfiles/deltarpm/base-version/@ver=*) 3259 deltabasever=${line##*=} ;; 3260 atoms/package/pkgfiles/deltarpm/base-version/@rel=*) 3261 deltabaserel=${line##*=} 3262 cacheinfo=pkg_${pkg//[^a-zA-Z0-9_]/_} cacheinfo=(${!cacheinfo}) 3263 currentversion=${cacheinfo[0]} 3264 myEcho 2 "Checking if delta RPM $deltabasever-$deltabaserel for $pkg-$currentversion works ..." 3265 if [[ -n $deltaseqinfo && $deltabasever-$deltabaserel == $currentversion ]] && applydeltarpm -c -s "$deltaseqinfo" 2>/dev/null ; then 3266 myWarn 3 "Found delta for $pkg: $deltarpm1" 3267 deltasize=$deltasize1 3268 deltarpm=$deltarpm1 3269 else 3270 deltasize=0 3271 deltarpm=unknown 3272 fi 3273 ;; 3274 atoms/package/pkgfiles/deltarpm/base-version/@sequence_info=*) 3275 deltaseqinfo=${line##*=} ;; 3276 atoms/script/do=*) 3277 scriptcode=${line##*=} ; scriptcode=${scriptcode/// 3278 } 3279 processXMLDescRPM ;; 3280 # *) echo "line $line" ;; 3281 esac 3282 done < $xmlparsed 3283 if [[ $readingPkg -eq 1 ]] ; then 3284 processXMLDescRPM 3285 fi 3286 rm -f $xmlparsed 3287 done 3288 } 3289 3290 ################################# processPatchDescriptions 3291 # cycle through all package description files 3292 # Parameters: 3293 # $*: the patch description files 3294 function processPatchDescriptions() 3295 { 3296 local rpm pkg newversion size newbuildtime filename patchbase patchsize 3297 local sourcerpm readingPkg series updateinfoshown shortdesc newhdsize kind 3298 local POSTINFO PREINFO FORCEINSTALL PENDINGCOUNT PENDINGARRAY 3299 local UPDATEONLYINSTALLED SAFEPKGDESC i deltasize deltarpm 3300 myEcho 2 "Need to check $# package information files on $server" 3301 [[ $# -eq 0 ]] && return 3302 [[ $USEPROGRESS -eq 1 ]] && MAXCOUNT=`grep ^Filename: $* 2>/dev/null| wc -l` 3303 [[ $MAXCOUNT == 0 ]] && MAXCOUNT=1 # otherwise div/0 would occur ... 3304 ALLCOUNT=0 # reset progress bar 3305 for i in $* ; do 3306 pkgdescname=${i##*/} 3307 myNote 3 "########## Processing patch description $i" 3308 [[ ! -f $i ]] && myWarn 2 "Missing patch description $i" && continue 3309 cachefile=$CACHEDIR/.cache.$HOSTNAME/$i.$LANGUAGE 3310 newbuildtime=0 3311 rpm=unknown pkg=unknown newversion=0.0-0 size=0 newbuildtime=0 newhdsize=0 3312 filename=unknown.rpm patchbase= patchsize=0 sourcerpm=unknown oldhdsize=0 3313 kind=unknown 3314 readingPkg=0 #currently (not) reading a package info from the pkgdesc file 3315 series=default # initialisation to sane defaults 3316 updateinfoshown=0 # indicates if update information has been shown 3317 shortdesc= # short description 3318 POSTINFO=0 # postinstall information present? 3319 FORCEINSTALL=0 # force installation because of installtrigger 3320 PREINFO=0 PENDINGCOUNT=0 PENDINGARRAY=() 3321 UPDATEONLYINSTALLED=0 # default!! 3322 SAFEPKGDESC=$SKIPGPG # use default from disable gpg option 3323 deltarpm=unknown deltasize=0 3324 if [[ $USECACHE -ge 1 ]] ; then 3325 if [[ -f $cachefile && $cachefile -nt $i ]] ; then 3326 for cf in $cachefile.* ; do 3327 if [[ -f $cf ]] ; then 3328 source $cf 3329 if [[ $LISTAVAILRPMS -eq 1 ]] ; then # only show available rpms 3330 showRpmSummary 3331 else 3332 checkPackage 3333 fi 3334 fi 3335 done 3336 continue 3337 fi 3338 mkdir -p ${cachefile%/*} # create directory for cache file 3339 rm -f $cachefile* 3340 touch $cachefile # empty dummy 3341 fi 3342 while read tag rest; do 3343 if [[ -z $tag && $readingPkg -eq 0 ]] ; then 3344 continue 3345 fi 3346 tag=${tag//\`/} # kill special shell characters 3347 tag=${tag//\$(/} # kill special shell characters 3348 # if we are currently reading a package, it is finished with one of 3349 # the following strings 3350 if [[ $readingPkg -eq 1 ]] ; then 3351 processpkg=0 3352 case "$tag" in 3353 Segakcap:|-----BEGIN|Filename:) 3354 [[ $pkg != unknown && -n $pkg ]] && processpkg=1 ;; 3355 esac 3356 if [[ $processpkg -eq 1 ]] ; then 3357 if [[ $LISTAVAILRPMS -eq 1 ]] ; then # only show available rpms 3358 showRpmSummary 3359 else 3360 pkg=${pkg%%-$newversion*} 3361 pkg1=${pkg//[^a-zA-Z0-9_-]/} 3362 if [[ $USECACHE -ge 1 ]] ; then 3363 for p in pkg rpm newversion kind size newbuildtime series filename shortdesc patchbase patchsize newhdsize sourcerpm PREINFO POSTINFO UPDATEONLYINSTALLED deltasize deltarpm; do 3364 echo "$p='${!p//\'/\"}'" >> $cachefile.$pkg1 3365 done 3366 fi 3367 checkPackage # "$pkg" "$rpm" "$newversion" "$kind" "$size" "$patchsize" "$newbuildtime" "$series" "$filename" "$shortdesc" 3368 fi 3369 # reset values in case that the next loop will not refill them 3370 series=default rpm=unknown pkg=unknown filename=unknown.rpm 3371 newversion=0.0-0 size=0 newbuildtime=0 readingPkg=0 shortdesc= 3372 patchbase= patchsize=0 sourcerpm=unknown newhdsize=0 deltasize=0 3373 deltarpm=unknown 3374 fi 3375 fi 3376 3377 case "$tag" in # get tags from patch description 3378 Deltas:) 3379 [[ $readingPkg -eq 0 ]] && continue 3380 [[ $USEDELTARPMS -lt 0 ]] && continue 3381 while true ; do 3382 read tag rest 3383 [[ $tag == Satled: ]] && break 3384 rest=($rest) # make array 3385 myEcho 2 "Checking if delta RPM for $pkg works ..." 3386 if applydeltarpm -c -s "${rest[5]}" 2>/dev/null ; then 3387 # we assume that there is only one matching delta rpm 3388 deltasize=${rest[0]} 3389 deltarpm="$tag" 3390 myEcho 3 "Found delta for $pkg: $tag" 3391 fi 3392 done 3393 ;; 3394 UpdateOnlyInstalled:) 3395 if [[ $rest == true ]] ; then 3396 UPDATEONLYINSTALLED=1 3397 fi ;; 3398 Filename:) 3399 pkg=${rest%%.rpm} 3400 readingPkg=1 # we have found a new package within the pkgdesc 3401 filename=$rest ;; 3402 Version:) 3403 newversion=$rest 3404 if [[ -z $newversion ]] ; then 3405 newversion=fix-me 3406 [[ $VERBOSE -ge 1 ]] && \ 3407 echo "Invalid version found in $i! Please read http://fou4s.gaugusch.at/problems.shtml and report to fou4s@gaugusch.at if it is not known." | fmt -$COLUMNS 3408 fi ;; 3409 BuiltFrom:) 3410 sourcerpm="rpm/src/$rest" ;; 3411 Prescript:*|Postscript:*) 3412 series=script 3413 FORCEINSTALL=1 # because we have no version comparison 3414 [[ -z $rest ]] && rest=${tag##Prescript:} # fix missing blank 3415 pkg=$rest rpm=scripts/$rest newversion=script kind=script size=0 3416 pkg1=$pkg 3417 patchsize=0 newbuildtime=0 3418 if [[ $USECACHE -ge 1 ]] ; then 3419 for p in pkg rpm newversion kind size patchsize newbuildtime series filename shortdesc patchbase newhdsize sourcerpm PREINFO POSTINFO UPDATEONLYINSTALLED FORCEINSTALL; do 3420 echo "$p='${!p//\'/\"}'" >> $cachefile.$pkg1 3421 done 3422 fi 3423 checkPackage # "$rest" "scripts/$rest" "script" "script" "0" "0" "0" "$series" "$rest" "$shortdesc" 3424 break ;; 3425 Shortdescription.english:) 3426 [[ -z $shortdesc ]] && shortdesc=${rest//\`/\'} shortdesc=${shortdesc//$/$ } ;; # vim syntax helper: ' 3427 Shortdescription.$LANGUAGE:) 3428 [[ -n $rest ]] && shortdesc=${rest//\`/\'} shortdesc=${shortdesc//$/$ } ;; # vim syntax helper: ' 3429 InstPath:) 3430 rpm=$rest ;; 3431 Kind:) 3432 kind=$rest ;; 3433 Postinformation.english*|Postinformation.$LANGUAGE*) 3434 POSTINFO=1 ;; 3435 Preinformation.english*|Preinformation.$LANGUAGE*) 3436 PREINFO=1 ;; 3437 Series:) 3438 series=$rest 3439 if [[ $NODOTSUSEVERSION -ge 92 ]] ; then 3440 [[ -n $series && $series != default && $series != @(${VALIDARCHS// /|}) ]] && readingPkg=0 && myEcho 2 Ignoring package $pkg with foreign arch $series 3441 fi 3442 [[ -z $series ]] && series="default" ;; 3443 Size:) 3444 [[ $readingPkg -eq 0 ]] && continue 3445 size=($rest) # convert to an array 3446 newhdsize=${size[0]} 3447 size=${size[1]} # get second field 3448 if [[ -z $size ]] ; then 3449 size=0 3450 [[ -n $newhdsize ]] && size=$newhdsize 3451 myEcho 2 "$pkg: Invalid size! Using $size" 3452 fi 3453 ;; 3454 PatchRpmSize:) 3455 rest=($rest) 3456 patchsize=${rest[1]} # get second field 3457 ;; 3458 PatchRpmBasedOn:) 3459 patchbase=$rest 3460 ;; 3461 Buildtime:) 3462 newbuildtime=$rest ;; 3463 Installtrigger:) 3464 if [[ $SAFEMODE -eq 0 && $i != *-G ]] ; then 3465 hasGoodSignature "`gpg --no-tty --verify "$i" 2>&1`" DSA 9C800ACA "SuSE Package Signing Key <build@suse.de>" 3466 ret=$? 3467 if [[ $ret -eq 0 ]] ; then 3468 SAFEPKGDESC=1 3469 elif [[ $ret -eq 254 ]] ; then 3470 myEcho 3 "No signature in patch description ${i##*/} - using safe mode!" 3471 else 3472 [[ $QUIET -eq 0 ]] && myEcho 0 "Invalid signature in patch description ${i##*/} - using safe mode!" 3473 fi 3474 fi 3475 handleInstallTrigger ;; 3476 esac; 3477 done < $i 3478 done 3479 } # processPatchDescriptions 3480 3481 3482 ################################# addToSkippedPatches 3483 # Adds one or more entries to the skipped-patches file 3484 # parameters: 3485 # $*: The entries to add 3486 function addToSkippedPatches() 3487 { 3488 local pwd=$PWD 3489 cd "$BASEDIR" 3490 printf "%s\n" $* >> $SKIPPEDPATCHESFILE 3491 cd "$pwd" 3492 3493 # prevent creating cache with bogus data at end of program 3494 [[ $USECACHE -eq 2 ]] && USECACHE=1 3495 rm -f $DESCCACHE $AUTOSKIPPEDPATCHESFILE &>/dev/null #force creation next time 3496 } # addToSkippedPatches 3497 3498 3499 ################################# getOptionsFromConfigFile 3500 # get options from config file 3501 # Parameters: 3502 # $1: filename 3503 function getOptionsFromConfigFile() 3504 { 3505 local CONFIGFILE=$1 3506 if [[ -f $CONFIGFILE ]] ; then 3507 while read optval ; do 3508 optval=${optval%%#*} 3509 [[ -z $optval ]] && continue 3510 key=${optval%%=*} 3511 value=${optval#*=} 3512 case $key in 3513 DefaultVerbosity) 3514 VERBOSE=`checkOption "$value" $key $VERBOSE range 0 3` ;; 3515 Proxy) 3516 export ALL_PROXY=`checkOption "$value" $key $ftp_proxy` 3517 export http_proxy=`checkOption "$value" $key $http_proxy` 3518 export https_proxy=`checkOption "$value" $key $https_proxy` 3519 export HTTPS_PROXY=`checkOption "$value" $key $https_proxy` 3520 export ftp_proxy=`checkOption "$value" $key $ftp_proxy` 3521 export FTP_PROXY=`checkOption "$value" $key $ftp_proxy` ;; 3522 AcceptPreinstallInfo) 3523 ACCEPTPREINSTALLINFO=`checkOption "$value" $key $ACCEPTPREINSTALLINFO` ;; 3524 Arch) 3525 ARCH=`checkOption "$value" $key $ARCH` 3526 FORCEDARCH=$ARCH ;; 3527 Auto) 3528 AUTOLIST=`checkOption "$value" $key "$AUTOLIST"` ;; 3529 Benchmark) 3530 BENCHMARK=`checkOption "$value" $key $BENCHMARK bool` ;; 3531 CacheDir) 3532 CACHEDIR=`checkOption "$value" $key $CACHEDIR` ;; 3533 CheckFou4s) 3534 CHECKFOU=`checkOption "$value" $key $CHECKFOU bool` ;; 3535 ColorOutput) 3536 COLOR=`checkOption "$value" $key $COLOR bool` ;; 3537 Compatible) 3538 COMPATIBLE=`checkOption "$value" $key $COMPATIBLE bool` ;; 3539 DescriptionCache) 3540 USECACHE=`checkOption "$value" $key $USECACHE range 0 2` ;; 3541 Exclude) 3542 EXCLUDELIST=`checkOption "$value" $key "$EXCLUDELIST"` ;; 3543 KernelBackup) 3544 KERNELBACKUP=`checkOption "$value" $key "$KERNELBACKUP" bool` ;; 3545 KernelCheck) 3546 KERNELCHECK=`checkOption "$value" $key "$KERNELCHECK" bool` ;; 3547 Language) 3548 LANGUAGE=`checkOption "$value" $key "$LANGUAGE"` ;; 3549 RpmDir) 3550 DLPATH=`checkOption "$value" $key $DLPATH` ;; 3551 SuSEUser) 3552 HTTPUSER=`checkOption "$value" $key $HTTPUSER` ;; 3553 SuSEPassword) 3554 HTTPPASSWD=`checkOption "$value" $key $HTTPPASSWD` ;; 3555 TestMode) 3556 TESTMODE=`checkOption "$value" $key $TESTMODE bool` ;; 3557 IgnoreList) 3558 IGNORELIST=`checkOption "$value" $key "$IGNORELIST"` ;; 3559 Interactive) 3560 INTERACTIVE=`checkOption "$value" $key $INTERACTIVE bool` ;; 3561 InverseColor) 3562 INVERSE=`checkOption "$value" $key $INVERSE bool` 3563 [[ $INVERSE -eq 1 ]] && BRIGHT=0 ;; 3564 LogFile) 3565 LOGFILE=`checkOption "$value" $key $LOGFILE` ;; 3566 LogLevel) 3567 LOGLEVEL=`checkOption "$value" $key $LOGLEVEL range 0 3` ;; 3568 OlderThan) 3569 DAYSOLDER=`checkOption "$value" $key $LOGLEVEL range 0 10000` ;; 3570 ProxyDigest) 3571 PROXYDIGEST=`checkOption "$value" $key $PROXYDIGEST bool` ;; 3572 ProxyUser) 3573 PROXYUSER=`checkOption "$value" $key $PROXYUSER` ;; 3574 ProxyPasswd) 3575 PROXYPASS=`checkOption "$value" $key $PROXYPASS` ;; 3576 RemarkList) 3577 REMARKLIST=`checkOption "$value" $key "$REMARKLIST"` ;; 3578 RemoveAfterInstall) 3579 REMOVE=`checkOption "$value" $key $REMOVE bool` ;; 3580 Server) 3581 SERVERLIST="$SERVERLIST `checkOption "$value" $key "$SERVERLIST"`";; 3582 SourceRpms) 3583 SRCRPMS="$SRCRPMS `checkOption "$value" $key "$SRCRPMS"`";; 3584 SuSEProduct) 3585 SUSEPRODUCT=`checkOption "$value" $key "$SUSEPRODUCT"` ;; 3586 SuSEVersion) 3587 SUSEVERSION=`checkOption "$value" $key $SUSEVERSION` ;; 3588 UseDeltaRpms) 3589 USEDELTARPMS=`checkOption "$value" $key $USEDELTARPMS bool` ;; 3590 UseCurl) 3591 USECURL=`checkOption "$value" $key $USECURL` ;; 3592 UseDir) 3593 USEDIR=`checkOption "$value" $key $USEDIR` ;; 3594 UsePatchRpms) 3595 PATCHRPMS=`checkOption "$value" $key $PATCHRPMS bool` ;; 3596 PackageListDir|RSyncServer|GpdList|UseFullPath) 3597 myWarn 0 "Fou4s Warning: Please remove the obsolete option $key from $CONFIGFILE";; 3598 *) 3599 myError 0 "Error: Unknown option in $CONFIGFILE: $key" 3600 exit 2 ;; 3601 esac 3602 done < $CONFIGFILE 3603 fi 3604 } # getOptionsFromConfigFile vim" 3605 3606 3607 # 'compile' the lists into patterns 3608 # need to squeeze separators first 3609 # then introduce | as separator 3610 function listsToPatterns() 3611 { 3612 local listvar tmp 3613 set -f # no globbing 3614 # eval because it makes extension easier 3615 for listvar in $*; do 3616 IFS=$' \t\n,'; tmp=(${!listvar}) # split on whitespace and comma 3617 IFS="|"; eval $listvar="'${tmp[*]}'" # join with "|" 3618 IFS=$' \t\n' # restore standard IFS 3619 done 3620 set +f 3621 } # listsToPatterns vim" 3622 3623 3624 ################################# revert 3625 # Revert a text and change first letter to a capital 3626 function revert() 3627 { 3628 local i j text=$1 res first 3629 text=`echo "$text" | tr '[A-Z]' '[a-z]'` 3630 local len=${#text} 3631 len=$((len-1)) 3632 for i in `seq 1 $len` ; do 3633 i=$((i-1)) 3634 j=$((i-1)) 3635 res="${text:$i:1}$res" 3636 done 3637 res="`echo ${text:$len:1} | tr "[a-z]" "[A-Z]"`$res" 3638 echo $res 3639 } # revert 3640 3641 3642 ################################# optionPostProcessing 3643 # updates some variables after all options and arguments have been read 3644 function optionPostProcessing() 3645 { 3646 local o 3647 [[ -x `which dcop &>/dev/null` && -n $KONSOLE_DCOP_SESSION ]] && o=`dcop $KONSOLE_DCOP_SESSION schema` && [[ $o == "" ]] && INVERSE=1 3648 [[ $INVERSE -eq 1 ]] && BRIGHT=0 3649 # use color if stdin is a terminal - use | less -R to get colored 3650 # output when piping to less! 3651 if [[ $COLOR -eq 1 && -t 0 ]]; then 3652 COL_RED="\033[$BRIGHT;31m" 3653 COL_GREEN="\033[$BRIGHT;32m" 3654 COL_YELLOW="\033[$BRIGHT;33m" 3655 COL_WHITE="\033[$BRIGHT;37m" 3656 COL_CYAN="\033[$BRIGHT;36m" 3657 COL_BLACK="\033[0;30m" 3658 COL_NORM="\033[0m" 3659 if [[ $INVERSE -eq 1 ]] ; then 3660 COL_WHITE="\033[$BRIGHT;30m" # black 3661 COL_YELLOW="\033[0;33m" # dark yellow 3662 COL_CYAN="\033[$BRIGHT;34m" # blue 3663 fi 3664 fi 3665 # determine suse version from filename of rpmcache when in offline mode 3666 EGAUGNAL=`revert $LANGUAGE` # reverse string of language 3667 if [[ $LANGUAGE != english && -f `which recode 2>&1` ]] ; then 3668 DORECODE=1 3669 fi 3670 RPMVER=`rpm --version` # used for signature verification 3671 RPMVER=${RPMVER##*version } 3672 [[ $RPMVER == 4.0* ]] && RPMVER=30 # hack for puretec suse 8.0 with rpm v4 3673 [[ $RPMVER == 4.4.* ]] && RPMVER=44 3674 [[ $RPMVER == 4.7.* ]] && RPMVER=47 3675 [[ $RPMVER == 4.8.* ]] && RPMVER=48 3676 [[ $RPMVER == 4.9.* ]] && RPMVER=49 3677 RPMVER=${RPMVER%%.*} 3678 [[ -z $RPMVER ]] && RPMVER=30 # just for safety 3679 [[ $RPMVER -lt 10 ]] && RPMVER=${RPMVER}0 3680 if [[ -t 0 ]] ; then 3681 COLUMNS=`stty size| cut -d " " -f 2` 3682 fi 3683 [[ -z $COLUMNS ]] && COLUMNS=80 3684 3685 if [[ $EXPORT -eq 1 && $EXPORTFILE == *.tar ]] ; then 3686 [[ $EXPORTFILE != /* ]] && EXPORTFILE="$PWD/${EXPORTFILE#./}" 3687 OFFLINE=1 # don't query host if exporting for it! 3688 SUSEVERSION="*[0-9]" # must end with a number 3689 elif [[ $EXPORT -eq 1 && $EXPORTFILE != *.fou ]] ; then 3690 myError 0 "The parameter --export takes either a .fou file (offline machine) or a .tar file (internet connected machine)" | fmt -$COLUMNS 3691 exit 14 3692 fi 3693 3694 # if [[ $MACHINEARCH == i?86 ]] ; then # don't allow i686 on i586 machines, etc 3695 # VALIDARCHS=noarch 3696 # for a in i386 i486 i586 i686 i786 ; do 3697 # VALIDARCHS="$VALIDARCHS $a" 3698 # [[ $a == $MACHINEARCH ]] && break 3699 # done 3700 # elif [[ $MACHINEARCH == x86_64 ]] ; then #amd64 also works with ix86 pkg 3701 # VALIDARCHS="noarch i386 i486 i586 i686 x86_64" 3702 # fi 3703 RPMCACHE=$CACHEDIR/.cache.$HOSTNAME/rpmcache.$SUSEVERSION # cache file with all versions 3704 if [[ $SUSEVERSION == \*\[0-9\] ]] ; then 3705 SUSEVERSION=`echo $RPMCACHE` # glob filename 3706 if [[ $SUSEVERSION == *\ * ]] ; then 3707 myError 0 "More than one cache file was found, please check $RPMCACHE" 3708 exit 20 3709 fi 3710 SUSEVERSION=${SUSEVERSION##*/} # strip path 3711 SUSEVERSION=${SUSEVERSION#*.} # strip "rpmcache." 3712 NODOTSUSEVERSION=${SUSEVERSION//.} # rebuild 3713 RPMCACHE=$CACHEDIR/.cache.$HOSTNAME/rpmcache.$SUSEVERSION # rebuild 3714 fi 3715 3716 if [[ $OFFLINE -eq 1 && ! -f $RPMCACHE ]] ; then 3717 myError 0 "RPM cache for host $HOSTNAME not found - please import with --import or don't use --offline" | fmt -$COLUMNS 3718 myError 2 "Cachefile is $RPMCACHE" 3719 exit 15 3720 fi 3721 if [[ $IMPORT -eq 1 && -f $IMPORTFILE ]] ; then 3722 if [[ $IMPORTFILE == *.fou ]] ; then 3723 SUSEVERSION=`zgrep '^SUSEVERSION=' "$IMPORTFILE"` 3724 SUSEVERSION=${SUSEVERSION##SUSEVERSION=} 3725 SUSEPRODUCT=`zgrep '^SUSEPRODUCT=' "$IMPORTFILE"` 3726 SUSEPRODUCT=${SUSEPRODUCT##SUSEPRODUCT=} 3727 RPMCACHEVERSION=`zgrep '^RPMCACHEVERSION=' "$IMPORTFILE"` 3728 RPMCACHEVERSION=${RPMCACHEVERSION##RPMCACHEVERSION=} 3729 HOSTNAME=`zgrep '^HOSTNAME=' "$IMPORTFILE"` 3730 HOSTNAME=${HOSTNAME##HOSTNAME=} 3731 if [[ $HOSTNAME == `hostname` ]] ; then 3732 myError 0 "Cannot import for localhost! Use --host to specify the host" 3733 exit 15 3734 fi 3735 if [[ $RPMCACHEVERSION != $RPMCACHEVER ]] ; then 3736 myError 0 "The exporting machine uses a too old version of fou4s, import failed!" 3737 exit 15 3738 fi 3739 cleanCache 3740 RPMCACHE=$CACHEDIR/.cache.$HOSTNAME/rpmcache.$SUSEVERSION # cache file with all versions 3741 if [[ ! -d `dirname $RPMCACHE.gz` ]] ; then 3742 mkdir -p `dirname $RPMCACHE.gz` 3743 fi 3744 cp "$IMPORTFILE" $RPMCACHE.gz && rm -f $RPMCACHE 3745 gunzip $RPMCACHE.gz 3746 myNote 0 "Successfully imported `basename $IMPORTFILE` (${SUSEPRODUCT:=SuSE} $SUSEVERSION) from host $HOSTNAME. Now run" 3747 myNote 0 "fou4s -u --host $HOSTNAME --export myExport.tar" 3748 myWarn 0 "Then copy myExport.tar to target machine and run" 3749 myNote 0 "fou4s --import myExportfile.tar -i" 3750 exit 0 3751 elif [[ $IMPORTFILE == *.tar ]] ; then 3752 myNote 0 "Importing packages ..." 3753 if [[ $IMPORTFILE != /* ]] ; then 3754 IMPORTFILE=$PWD/$IMPORTFILE # relative path to fixed path conversion 3755 fi 3756 for SERVERURL in $SERVERLIST; do 3757 server=${SERVERURL#@(ftp|http|https|rsync)://} server=${server%%/*} 3758 server=${server##*@} 3759 break # only use first server 3760 done 3761 cd "$BASEDIR" ; 3762 mkdir -p "$DLPATH/$server" 3763 cd "$DLPATH/$server" 3764 tar xf $IMPORTFILE 3765 myNote 0 "Successfully imported `basename $IMPORTFILE`" 3766 exit 0 3767 else 3768 myError 0 "Error: Importfile must be named '*.fou' or '*.tar'!" 3769 exit 16 3770 fi 3771 elif [[ $IMPORT -eq 1 ]] ; then 3772 myError 0 "Error: Importfile $IMPORTFILE does not exist!" 3773 exit 16 3774 fi 3775 # diable progressbar on verbose level ge 2 3776 [[ $VERBOSE -lt 2 ]] || USEPROGRESS=0 3777 3778 if [[ $LIMIT -ne 0 ]] ; then 3779 RSYNCOPTS="$RSYNCOPTS --bwlimit $LIMIT" 3780 GLOBALWGETOPTS="$GLOBALWGETOPTS --limit-rate ${LIMIT}k" 3781 GLOBALCURLOPTS="$GLOBALCURLOPTS --limit-rate ${LIMIT}k" 3782 fi 3783 3784 # NODOTSUSEVERSION=${SUSEVERSION//./} # SuSE version without dots for comparisons # removed because of SLES9 bug (C. Thiel) 3785 SERVERLIST=${SERVERLIST//,/ } # remove "," and replace with space 3786 #DLPATH=$CACHEDIR/packages # default path for downloaded RPMs # FIXME don't overwrite always, only if dlpath has default value 3787 DESCCACHE=$CACHEDIR/.cache.$HOSTNAME/descriptioncache.$SUSEVERSION # cache of patch descriptions 3788 listsToPatterns AUTOLIST EXCLUDELIST IGNORELIST REMARKLIST USERRPMS SRCRPMS 3789 3790 if [[ $SERVERLIST == *rsync://* && -z `type -p rsync` ]] ; then 3791 myError 0 "You have an rsync server configured, but rsync is not installed. Aborting!" 3792 exit 9 3793 fi 3794 if [[ -z `type -p wget` ]] ; then 3795 myEcho 2 "wget not found, falling back to curl ..." 3796 USECURL=1 3797 fi 3798 # curl requires usedir (don't move into above if, because USECURL might 3799 # be set by an option or parameter as well!) 3800 [[ $USECURL -eq 1 ]] && USEDIR=1 3801 [[ $NODOTSUSEVERSION -ge 101 ]] && USEDIR=1 3802 [[ $NODOTSUSEVERSION -ge 110 ]] && PATCHRPMS=0 3803 3804 # output colum sizes 3805 [[ -n $COLUMNS && $COLUMNS -gt 86 ]] && RWIDTH=$((RWIDTH+COLUMNS-86)) 3806 3807 if [[ $GETSOURCE -eq 1 && $DOINSTALL -eq 1 ]] ; then 3808 myError 0 "Source RPM's cannot be installed. Use fou4s -ed to download them and copy from $DLPATH/.../rpm/src to a directory of your choice." | fmt -$COLUMNS 3809 exit 10 3810 fi 3811 3812 if [[ -n $SUSEPRODUCT ]] ; then 3813 SUSEPRODUCT=$SUSEPRODUCT/ # append slash 3814 if [[ $SERVERLIST == *ftp.gwdg.de* ]] ; then 3815 myWarn 0 "You are using ftp.gwdg.de and a business product, this will probably not work. Set SuSEUser= and SuSEPassword= in fou4s.conf and use sdb.suse.de as update server." | fmt -$COLUMNS 3816 echo 3817 fi 3818 if [[ -z $HTTPUSER && $AUTOMODE -eq 0 ]] ; then 3819 myWarn 0 "WARNING: You are using a business product and haven't given a username." 3820 myWarn 0 "Edit $CONFIGFILE and search for SuSEUser= and SuSEPassword=" 3821 fi 3822 fi 3823 if [[ -n $HTTPUSER && -n $HTTPPASSWD ]] ; then 3824 AUTHOPTS="--user $HTTPUSER --pass $HTTPPASSWD" 3825 elif [[ -n $HTTPUSER || -n $HTTPPASSWD ]] ; then 3826 myWarn 0 "WARNING: You must give a password for http auth, too!" 3827 fi 3828 3829 # must be set after reading config file and checking parameter 3830 if [[ -z $SUSEVERSION ]]; then 3831 myError 0 "Cannot determine SuSE-Version from /etc/SuSE-release or config file" 3832 myError 0 "Exiting..." 3833 exit 2 3834 fi 3835 [[ $NODOTSUSEVERSION -ge 101 ]] && SERVERPATH=update/$SUSEPRODUCT$SUSEVERSION || SERVERPATH=$ARCH/update/$SUSEPRODUCT$SUSEVERSION 3836 if [[ $NODOTSUSEVERSION -ge 101 && $SUSEVERSION == 10 ]] ; then 3837 SERVERPATH=/ # for SLES 10 3838 fi 3839 3840 if [[ -n $http_proxy && $http_proxy != http://*:*/ ]] ; then 3841 echo "Proxy must start with http:// and end with / (e.g. http://proxy:8080/)" 3842 echo "Please check your http_proxy environment variable" 3843 exit 11 3844 fi 3845 #if [[ -n $ftp_proxy ]] ; then 3846 # if [[ $ftp_proxy != http://*:*/ ]] ; then 3847 # echo "Proxy must start with http:// and end with / (e.g. http://proxy:8080/)" 3848 # echo "Please check your ftp_proxy environment variable" 3849 # exit 1 3850 # fi 3851 #fi 3852 3853 if [[ -n $PROXYUSER ]] ; then 3854 GLOBALWGETOPTS="$GLOBALWGETOPTS --proxy-user=$PROXYUSER" 3855 if [[ $PROXYDIGEST -eq 1 ]] ; then 3856 GLOBALCURLOPTS="$GLOBALCURLOPTS --proxy-digest -U $PROXYUSER:$PROXYPASS" 3857 USECURL=1 3858 else 3859 GLOBALCURLOPTS="$GLOBALCURLOPTS --proxy-basic -U $PROXYUSER:$PROXYPASS" 3860 fi 3861 fi 3862 3863 [[ -n $PROXYPASS ]] && GLOBALWGETOPTS="$GLOBALWGETOPTS --proxy-passwd=$PROXYPASS" 3864 3865 if [[ $BENCHMARK -eq 1 ]] ; then 3866 BSERVER="`fou4s-benchmark -q | head -1 | awk '{print $2}'`" 3867 if [[ -n $BSERVER ]] ; then 3868 SERVERLIST=$BSERVER 3869 echo "Using benchmarked server $SERVERURL" 3870 else 3871 myError 0 "Error: No benchmark server found! Using default ..." 3872 fi 3873 fi 3874 3875 if [[ $CHECKFOU -eq 1 && $NODOTSUSEVERSION -ge 101 ]] ; then 3876 SERVERLIST="http://fou4s.gaugusch.at $SERVERLIST" 3877 fi 3878 3879 if [[ ! -d $CACHEDIR/.cache.$HOSTNAME ]] ; then 3880 mkdir "$CACHEDIR/.cache.$HOSTNAME" 3881 fi 3882 Fou4skey=`echo $FOU4SKEY | tr "[A-Z]" "[a-z]"` 3883 3884 if [[ $NODOTSUSEVERSION -lt 92 ]] || ! type -p applydeltarpm >/dev/null ; then 3885 USEDELTARPMS=-1 3886 fi 3887 3888 if [[ $NODOTSUSEVERSION -ge 101 ]] ; then 3889 PATCHDIR=repodata 3890 fi 3891 for g in "$DIRNAME/xmlp.awk" /usr/bin/xmlp.awk /usr/local/bin/xmlp.awk ; do 3892 [[ -x $g ]] && XMLP=$g && break 3893 g="" 3894 done 3895 } # optionPostProcessing 3896 3897 3898 ################################# doStartupChecks 3899 # performs some initial checks that are needed for running fou4s 3900 function doStartupChecks() 3901 { 3902 if [[ ! -d $DLPATH ]] ; then 3903 echo "You need to create a directory to store the downloaded packages: $DLPATH (change $CONFIGFILE for a different path)"| fmt -$COLUMNS 3904 echo "Exiting ..." 3905 exit 2 3906 fi 3907 if [[ $CHECKONLY -eq 0 && $UPDATESERVERLIST -eq 0 && $UPDATEPACKAGELIST -eq \ 3908 0 && $DOINSTALL -eq 0 && $LISTAVAILRPMS -eq 0 && $EXPORT -eq 0 && \ 3909 $IMPORT -eq 0 ]] ; then 3910 echo "Please use one of -u, -e, -i, -l, --auto or --server!" 3911 exit 2 3912 fi 3913 [[ -f $CACHEDIR/descr_packages.$SUSEVERSION ]] && PACKAGES81=$CACHEDIR/descr_packages.$SUSEVERSION 3914 for f in $PACKAGES81 ; do 3915 if [[ ! -f $f ]] ; then 3916 myWarn 0 "Warning: $f can't be read. Run fou4s --fixperm to enable access for members of group fou4s or check if the 0x00000001 directory exists (create a link or rename the other one if not)." | fmt -80 3917 myWarn 0 "Alternatively, fou4s can download the file to $CACHEDIR/descr_packages.$SUSEVERSION (fou4s --getpackagedescriptions), if you are not root." | fmt -80 3918 # exit 1 3919 fi 3920 done 3921 if [[ $SKIPGPG -eq 0 && ! -x `type -p gpg` ]] ; then 3922 echo "GPG was not found. If you want to skip GPG signature checking, use" 3923 echo "the -g option. It is highly recommended to install gpg!" 3924 exit 2 3925 fi 3926 3927 if [[ $SKIPGPG -eq 0 ]] ; then 3928 # check for gnupg directory for RPM (currently only on 8.0) 3929 # it is used for key comparison when root installs packages. 3930 [[ -d /usr/lib/rpm/gnupg && $EUID -eq 0 ]] && export GNUPGHOME=/usr/lib/rpm/gnupg 3931 [[ $EUID -eq 0 && -z $HOME ]] && export HOME=/root 3932 3933 gpgproxyopt="--keyserver-options honor-http-proxy" 3934 if [[ $CHECKFOU -eq 1 ]] ; then 3935 if [[ `gpg --with-colons --list-keys $FOU4SKEY 2>/dev/null | grep ^pub: | cut -f1,3-6,10 -d:` != pub:1024:17:0EA1932BAFB66D7C:2002-04-28:fou4s\ build\ key\ \<fou4s@gaugusch.at\> && $RPMVER -lt 40 ]] ; then 3936 myNote 0 "Installing fou4s public key ..." 3937 if [[ -f ./fou4s_public.gpg ]] ; then 3938 gpg --import ./fou4s_public.gpg 3939 elif [[ -f /usr/share/doc/packages/fou4s/fou4s_public.gpg ]] ; then 3940 gpg --import /usr/share/doc/packages/fou4s/fou4s_public.gpg 3941 else 3942 gpg $gpgproxyopt --keyserver wwwkeys.pgp.net --recv-keys $FOU4SKEY 3943 fi 3944 fi 3945 if [[ $UPDATESERVERLIST -eq 0 && $RPMVER -ge 40 && `rpm -qi gpg-pubkey-$Fou4skey 2>/dev/null` == package\ gpg-pubkey-$Fou4skey\ is\ not\ installed ]] ; then 3946 myNote 0 "Installing fou4s public key (rpm V4)..." 3947 if [[ -f ./fou4s_public.gpg ]] ; then 3948 rpm --import ./fou4s_public.gpg 3949 elif [[ -f /usr/share/doc/packages/fou4s/fou4s_public.gpg ]] ; then 3950 rpm --import /usr/share/doc/packages/fou4s/fou4s_public.gpg 3951 fi 3952 fi 3953 fi 3954 if [[ `gpg --with-colons --list-keys 9C800ACA 2>/dev/null | grep ^pub: | cut -f1,3-6,10 -d:` != pub:1024:17:A84EDAE89C800ACA:2000-10-19:SuSE\ Package\ Signing\ Key\ \<build@suse.de\> && $RPMVER -lt 40 ]] ; then 3955 myNote 0 "Installing SuSE build key ..." 3956 gpg $gpgproxyopt --keyserver wwwkeys.pgp.net --recv-keys 9C800ACA 3957 fi 3958 fi 3959 3960 if [[ -d $DLPATH/server0 ]] ; then 3961 echo "Converting numbered to named server directories ..." 3962 i=0 3963 for SERVERURL in $SERVERLIST; do 3964 if [[ ${BASH_VERSINFO[0]} -ge 3 ]] ; then 3965 SERVERURL=${SERVERURL//\%ARCH/$ARCH} 3966 SERVERURL=${SERVERURL//\%VERSION/$SUSEVERSION} 3967 else 3968 SERVERURL=${SERVERURL//\\%ARCH/$ARCH} 3969 SERVERURL=${SERVERURL//\\%VERSION/$SUSEVERSION} 3970 fi 3971 server=${SERVERURL#@(ftp|http|https|rsync)://} server=${server%%/*} 3972 server=${server##*@} # strip username part of urls 3973 if [[ ! -d $DLPATH/$server ]] ; then 3974 mv -vf $DLPATH/server$i $DLPATH/$server 3975 else # directory exists already - mv won't work 3976 cp -r $DLPATH/server$i/* $DLPATH/$server/ 3977 rm -rf $DLPATH/server$i 3978 fi 3979 i=$((i+1)) 3980 done 3981 fi 3982 [[ $QUIET -eq 1 ]] && USEPROGRESS=0 3983 [[ -t 1 ]] || USEPROGRESS=0 # test file descriptor of stdout 3984 } # doStartupChecks 3985 3986 3987 ################################# updateStatistics 3988 # Updates the counters for different update types 3989 function updateStatistics() 3990 { 3991 COUNTER[_ALL]=$((COUNTER[_ALL]+1)) 3992 SIZES[_ALL]=$((SIZES[_ALL]+size)) 3993 DLSIZES[_ALL]=$((DLSIZES[_ALL]+size-FOUNDSIZE)) 3994 [[ $newhdsize != 0 && $oldhdsize != 0 ]] && HDSIZES[_ALL]=$((HDSIZES[_ALL]+newhdsize-oldhdsize)) 3995 case $kind in 3996 security) 3997 SIZES[_SECURITY]=$((SIZES[_SECURITY]+size)) 3998 DLSIZES[_SECURITY]=$((DLSIZES[_SECURITY]+size-FOUNDSIZE)) 3999 [[ $newhdsize != 0 ]] && HDSIZES[_SECURITY]=$((HDSIZES[_SECURITY]+newhdsize-oldhdsize)) 4000 COUNTER[_SECURITY]=$((COUNTER[_SECURITY]+1)) ;; 4001 recommended) 4002 SIZES[_RECOMMENDED]=$((SIZES[_RECOMMENDED]+size)) 4003 DLSIZES[_RECOMMENDED]=$((DLSIZES[_RECOMMENDED]+size-FOUNDSIZE)) 4004 [[ $newhdsize != 0 ]] && HDSIZES[_RECOMMENDED]=$((HDSIZES[_RECOMMENDED]+newhdsize-oldhdsize)) 4005 COUNTER[_RECOMMENDED]=$((COUNTER[_RECOMMENDED]+1)) ;; 4006 generated) 4007 SIZES[_GENERATED]=$((SIZES[_GENERATED]+size)) 4008 DLSIZES[_GENERATED]=$((DLSIZES[_GENERATED]+size-FOUNDSIZE)) 4009 [[ $newhdsize != 0 ]] && HDSIZES[_GENERATED]=$((HDSIZES[_GENERATED]+newhdsize-oldhdsize)) 4010 COUNTER[_GENERATED]=$((COUNTER[_GENERATED]+1)) ;; 4011 optional) 4012 SIZES[_OPTIONAL]=$((SIZES[_OPTIONAL]+size)) 4013 DLSIZES[_OPTIONAL]=$((DLSIZES[_optional]+size-FOUNDSIZE)) 4014 [[ $newhdsize != 0 ]] && HDSIZES[_OPTIONAL]=$((HDSIZES[_OPTIONAL]+newhdsize-oldhdsize)) 4015 COUNTER[_OPTIONAL]=$((COUNTER[_OPTIONAL]+1)) ;; 4016 YaST2) 4017 SIZES[_YAST]=$((SIZES[_YAST]+size)) 4018 DLSIZES[_YAST]=$((DLSIZES[_YAST]+size-FOUNDSIZE)) 4019 [[ $newhdsize != 0 ]] && HDSIZES[_YAST]=$((HDSIZES[_YAST]+newhdsize-oldhdsize)) 4020 COUNTER[_YAST]=$((COUNTER[_YAST]+1)) ;; 4021 script) 4022 SIZES[_SCRIPT]=$((SIZES[_SCRIPT]+size)) 4023 COUNTER[_SCRIPT]=$((COUNTER[_SCRIPT]+1)) 4024 DLSIZES[_SCRIPT]=$((DLSIZES[_SCRIPT]+size-FOUNDSIZE)) 4025 esac 4026 [[ $size == 0 ]] && COUNTER[_ZERO]=$((COUNTER[_ZERO]+1)) #wrong size cnt 4027 } # updateStatistics 4028 4029 4030 4031 ################################# addToRpmExportList 4032 # If --export *.tar is given, we save all found packages to that file 4033 function addToRpmExportList() 4034 { 4035 local rpm=${1##*$DLPATH/$server/} 4036 if [[ $EXPORT -eq 1 ]] ; then 4037 pushd "$BASEDIR">/dev/null 4038 if [[ $rpm == /* ]] ; then # absolute path found (file from alternate server) 4039 pushd ${rpm%%/$ARCH/update/$SUSEVERSION/*}>/dev/null # go to alternate server 4040 rpm=$ARCH/update/${rpm##*$ARCH/update/} 4041 else 4042 pushd "$DLPATH/$server">/dev/null # go to current server 4043 fi 4044 myEcho 3 "Adding to export file $EXPORTFILE: $rpm" 4045 [[ -f $EXPORTFILE ]] && tar -rf "$EXPORTFILE" $rpm && myNote 0 "Added to exportfile: `basename "$rpm"`" ||\ 4046 myError 0 "Could not add $rpm to export file!"; 4047 popd >/dev/null # dlpath/server 4048 popd >/dev/null # basedir 4049 fi 4050 return 0 4051 } 4052 4053 4054 ################################# processFoundUpdates 4055 # Processes the updates that have been found 4056 # the information is gathered through the package_XXX variables 4057 function processFoundUpdates() 4058 { 4059 local last_shown packageinfo pkg x y newversion currentversion shortdesc test 4060 local longdesc license 4061 for pkg in ${!package_*} ; do 4062 cd "$BASEDIR" 4063 cd "$DLPATH" 4064 # package_$pkgdescfile_MG_$rpm 4065 x=${pkg##*_MG_} #current patch name 4066 y=${pkg##package_} y=${y%%_MG_*} #real patch description file containing pkg 4067 pkg=${!pkg} 4068 packageinfo=packageinfo_$x packageinfo=(${!packageinfo}) 4069 newversion=${packageinfo[0]} 4070 currentversion=${packageinfo[1]} 4071 kind=${packageinfo[2]} 4072 size=${packageinfo[3]} 4073 series=${packageinfo[4]} 4074 remarkonly=${packageinfo[5]} 4075 rpm=${packageinfo[6]} 4076 dlfile=${packageinfo[7]} 4077 server=${packageinfo[8]} 4078 oldhdsize=${packageinfo[9]} 4079 newhdsize=${packageinfo[10]} 4080 i=${packageinfo[11]} 4081 patchfile=${packageinfo[12]} 4082 newbuildtime=${packageinfo[13]} 4083 PREINFO=${packageinfo[14]} 4084 sourcerpm=${packageinfo[15]} 4085 origurl=${packageinfo[16]} 4086 SERVERPATH=${packageinfo[17]} 4087 usepatchrpmnow=${packageinfo[18]} 4088 patchsize=${packageinfo[19]} 4089 SERVERURL=${packageinfo[20]} 4090 usedeltarpmnow=${packageinfo[21]} 4091 deltasize=${packageinfo[22]} 4092 deltarpm=${packageinfo[23]} 4093 patchrpm=${packageinfo[24]} 4094 shortdesc=shortdesc_$x shortdesc=${!shortdesc} 4095 longdesc=longdesc_$x longdesc=${!longdesc} 4096 license=license_$x license=${!license} 4097 4098 if [[ $pkg == @($SRCRPMS) ]] ; then 4099 rpm=$sourcerpm 4100 dlfile=$SERVERURL/$SERVERPATH/$sourcerpm 4101 usepatchrpmnow=0 4102 fi 4103 4104 [[ $PATCHRPMS -eq 0 ]] && usepatchrpmnow=0 4105 [[ $USEDELTARPMS -eq 0 ]] && usedeltarpmnow=0 4106 4107 if [[ $usedeltarpmnow -eq 1 ]] ; then 4108 size=$deltasize 4109 [[ $NODOTSUSEVERSION -lt 101 ]] && rpm=deltas/$deltarpm || rpm=$deltarpm 4110 dlfile=$SERVERURL/$SERVERPATH/$rpm 4111 elif [[ $usepatchrpmnow -eq 0 && $rpm == *.patch.rpm ]] ; then 4112 rpm=${rpm%%.patch.rpm}.rpm 4113 origurl=${origurl%%.patch.rpm}.rpm 4114 dlfile=${dlfile%%.patch.rpm}.rpm 4115 elif [[ $usepatchrpmnow -eq 1 && $patchsize -gt 0 && $kind != script \ 4116 && $rpm != *.patch.rpm ]] ; then 4117 size=$patchsize 4118 rpm=${rpm%%.rpm}.patch.rpm 4119 origurl=${origurl%%.rpm}.patch.rpm 4120 dlfile=${dlfile%%.rpm}.patch.rpm 4121 elif [[ $usepatchrpmnow -eq 1 ]] ; then 4122 [[ $NODOTSUSEVERSION -ge 101 ]] && rpm=$patchrpm 4123 size=$patchsize 4124 fi 4125 if packageFiltered $pkg $kind $series; then 4126 myEcho 4 "Skipping $pkg because of filter" 4127 continue 4128 fi 4129 if [[ $NODOTSUSEVERSION -lt 110 && ! -f $i ]] ; then 4130 myWarn 2 "Package description file $i is missing, skipping $pkg" # | fmt -$COLUMNS 4131 continue 4132 fi 4133 if [[ $y != ${patchfile//[^A-Za-z0-9_]/_} && -n $patchfile ]] ; then 4134 myWarn 2 "Skipping $pkg from $y because used $patchfile" 4135 continue 4136 fi 4137 if [[ $last_shown != $patchfile ]] ; then 4138 updateinfoshown=0 4139 cd "$BASEDIR" 4140 cd "$DLPATH" 4141 if [[ -n $RPMINSTLIST && $INSTMODE -eq 1 ]] ; then 4142 rpmInstall $RPMINSTLIST 4143 RPMINSTLIST= 4144 fi 4145 fi 4146 last_shown=$patchfile 4147 showPackage || continue 4148 updateStatistics 4149 [[ $DOINSTALL -eq 0 && $DOWNLOAD -eq 0 ]] && continue 4150 if [[ $DOINSTALL -eq 0 && $DOWNLOAD -eq 1 && -n $FOUNDFILE ]] ; then 4151 if [[ $size == 0 ]] ; then 4152 myEcho 2 "$pkg: correct size is unknown, trying to resume download." 4153 elif [[ $FOUNDSIZE == $size ]] ; then 4154 myEcho 2 "$pkg: correct size in local mirror, no need to download $rpm" 4155 continue 4156 else 4157 myEcho 2 "$pkg: incorrect size in local mirror, trying to resume download ($FOUNDSIZE/$size)." 4158 fi 4159 fi 4160 getUserChoice || continue 4161 # download package if desired and return if it fails 4162 rpmpath=${rpm%/*} 4163 if [[ $DOWNLOAD -eq 1 ]] && ! getRpm "$rpm" "$pkg" "$size" "$dlfile" ; then 4164 if ! fileExists $server $rpm ; then 4165 # try alternate server 4166 dlfile1=dlfile1_$x 4167 dlfile1=${!dlfile1} 4168 if [[ -n $dlfile1 ]] ; then 4169 server=server1_$x 4170 server=${!server} 4171 getRpm $rpm $pkg $size $dlfile1 4172 fi 4173 fi 4174 fi 4175 fileExists $server $rpm || continue 4176 [[ $INTERACTIVE -eq 0 && $PREINFO -eq 1 && $ACCEPTPREINSTALLINFO -eq 0 &&\ 4177 $EXPORT -eq 0 ]] && continue 4178 4179 # update rpminstlist with pending packages (only if in you-compat mode) 4180 [[ $CHECKONLY -eq 1 ]] && continue 4181 if ! fileExists $server $rpm ; then 4182 myWarn 0 "File not found: $rpm - skipping." 4183 continue 4184 fi 4185 [[ $TESTMODE -eq 1 ]] && test=" (test mode)" 4186 if [[ $series != script ]] ; then 4187 processDownloadedRpm $pkg $rpm $newversion ${rpm##*/} 4188 elif [[ $INTERACTIVE -eq 1 ]] ; then 4189 processScript $pkg 4190 fi 4191 done # found updates 4192 } # processFoundUpdates 4193 4194 4195 ################################ processServerList 4196 # Cycles through all available servers and calls processPatchDescriptions 4197 # for each 4198 function processServerList() 4199 { 4200 local nonfiles files 4201 lastserver= 4202 for SERVERURL in $SERVERLIST ; do 4203 if [[ ${BASH_VERSINFO[0]} -ge 3 ]] ; then 4204 SERVERURL=${SERVERURL//\%ARCH/$ARCH} 4205 SERVERURL=${SERVERURL//\%VERSION/$SUSEVERSION} 4206 else 4207 SERVERURL=${SERVERURL//\\%ARCH/$ARCH} 4208 SERVERURL=${SERVERURL//\\%VERSION/$SUSEVERSION} 4209 fi 4210 server=${SERVERURL#@(ftp|http|https|rsync)://} server=${server%%/*} 4211 server=${server##*@} server=${server%:*} 4212 if [[ $SERVERURL != *$ARCH/update/$SUSEPRODUCT$SUSEVERSION* ]] && \ 4213 [[ $SERVERURL == rsync://* ]] ; then 4214 SERVERPATH=${SERVERURL#rsync://} 4215 SERVERPATH=${SERVERPATH#*/} # customized rsync server path 4216 else 4217 SERVERURL=${SERVERURL%%/$ARCH*} 4218 [[ $NODOTSUSEVERSION -ge 101 ]] && SERVERPATH=update/$SUSEVERSION || \ 4219 SERVERPATH=$ARCH/update/$SUSEPRODUCT$SUSEVERSION 4220 [[ $NODOTSUSEVERSION -eq 101 && $SUSEVERSION = 10 ]] && SERVERPATH=/ # for SLES10 4221 fi 4222 if [[ $SERVERURL == ftp://* && -n $ftp_proxy && $USEDIR -eq 0 && $USECURL -eq 0 ]] ; then 4223 echo 4224 myWarn 0 "WARNING: You are using an FTP server and ftp_proxy is set. Fou4s can't use the proxy, because wget makes some trouble with FTP over a proxy." | fmt -$COLUMNS 4225 echo 4226 unset ftp_proxy 4227 fi 4228 [[ $UPDATEPACKAGELIST -eq 1 ]] && updatePackagelist $server $SERVERPATH 4229 lastserver=$server 4230 [[ $CHECKONLY -eq 0 && $DOINSTALL -eq 0 && $LISTAVAILRPMS -eq 0 ]] && continue 4231 # quiet and verbose are set in automode! 4232 myEcho 2 "Processing server $SERVERURL" 4233 if [[ ! -f $SKIPPEDPATCHESFILE ]] ; then 4234 touch $SKIPPEDPATCHESFILE 2>/dev/null 4235 if [[ $? -ne 0 ]] ; then 4236 myWarn 0 "Could not create $SKIPPEDPATCHESFILE, consider changing CacheDir in $CONFIGFILE" | fmt -$COLUMNS 4237 fi 4238 fi 4239 PATCHGLOB=$PATCHDIR 4240 if [[ $GENERATED -eq 1 ]]; then 4241 PATCHGLOB="$PATCHGLOB/.*-[0-9G]*" 4242 else 4243 PATCHGLOB="$PATCHGLOB/.*-[0-9]*" 4244 fi 4245 if [[ $NODOTSUSEVERSION -ge 101 ]] ; then 4246 PATCHGLOB="$PATCHDIR/patch-*.xml" 4247 fi 4248 4249 cd "$BASEDIR" 4250 cd "$DLPATH" 4251 PKGDESCFILES= 4252 if [ $NODOTSUSEVERSION -lt 110 ] ; then 4253 if [[ $USEDIR -eq 1 ]] ; then 4254 if [[ $NODOTSUSEVERSION -lt 101 ]] ; then 4255 DIRFILES=`find ./$server/$SERVERPATH -follow -regex ".*\/directory.*" 2>/dev/null` 4256 PKGDESCFILES=`cat $DIRFILES| sed "s#^#./$server/$SERVERPATH/$PATCHDIR/#g"| grep -v -F -f $SKIPPEDPATCHESFILE` 4257 [[ -z $PKGDESCFILES ]] && myEcho 3 "No directory file found on $server" 4258 else 4259 pushd "$server/$SERVERPATH/$PATCHDIR" >/dev/null 4260 PKGDESCFILES=`parsePatchesXML -f ./$server/$SERVERPATH/$PATCHDIR/ |\ 4261 grep -v -F -f $SKIPPEDPATCHESFILE` 4262 popd >/dev/null 4263 fi 4264 elif [[ -z $PKGDESCFILES ]] ; then 4265 PKGDESCFILES=`find ./$server/$SERVERPATH/$PATCHDIR* -follow -regex ".*$PATCHGLOB" 2>/dev/null\ 4266 | grep -v -F -f $SKIPPEDPATCHESFILE` 4267 fi 4268 PKGDESCFILES=`echo $PKGDESCFILES | tr " " "\n" | sort -u` 4269 # if --nogenerated is used, we don't want to see this message 4270 if [[ -z $PKGDESCFILES && $GENERATED -eq 1 ]] ; then 4271 echo -e $COL_RED 4272 echo "WARNING: No update description files found for $SERVERURL" | fmt -$COLUMNS 4273 echo "Run fou4s with option -u to download patch descriptions!" 4274 echo 4275 echo -e "${COL_YELLOW}You may also want to check $SKIPPEDPATCHESFILE, this file contains all patch description names that will be skipped by fou4s. Make sure that it doesn't contain any blank lines!!" | fmt -$COLUMNS 4276 echo -e $COL_NORM 4277 continue 4278 fi 4279 ALLPKGDESCFILES="$ALLPKGDESCFILES $PKGDESCFILES" 4280 if [[ $EXPORT -eq 1 ]] ; then 4281 ( 4282 cd "$BASEDIR" 4283 cd "$DLPATH" 4284 cd $server 4285 for d in $ALLPKGDESCFILES ; do 4286 tar -rf "$EXPORTFILE" ${d##./$server/} 4287 done 4288 ) 4289 fi 4290 if [[ $USECACHE -ge 2 && -f $AUTOSKIPPEDPATCHESFILE ]] ; then 4291 myNote 2 "Processing auto-skipped patches on $server" 4292 nonfiles="`cat $AUTOSKIPPEDPATCHESFILE`" 4293 listsToPatterns nonfiles 4294 files=$PKGDESCFILES 4295 PKGDESCFILES= 4296 INVALIDPKGDESCS= 4297 for f in $files ; do 4298 if [[ $f == @($nonfiles) && -f $f && $f -ot $DESCCACHE ]] ; then 4299 myEcho 3 "Skipping $f" 4300 else 4301 PKGDESCFILES="$PKGDESCFILES $f" 4302 myNote 3 "Using $f" 4303 fi 4304 done 4305 myEcho 2 "Done with auto-skipped patches on $server" 4306 fi 4307 if [[ $NODOTSUSEVERSION -ge 101 ]] ; then 4308 processXMLPatchDescriptions $PKGDESCFILES # compares versions 4309 else 4310 processPatchDescriptions $PKGDESCFILES # compares versions 4311 fi 4312 else 4313 pushd "$server/$SERVERPATH/$PATCHDIR" >/dev/null 4314 processPrimaryXML 4315 fi 4316 [[ $USEPROGRESS -eq 1 ]] && showProgress 1 1 1 # force 100% display 4317 done # serverlist 4318 } # processServerList 4319 4320 4321 ################################# 4322 ################################# main program 4323 ################################# 4324 [[ $# -lt 1 ]] && showUsageShort 4325 [[ $1 = --config ]] && CONFIGFILES=$2 && shift 2 4326 for c in $CONFIGFILES ; do 4327 [[ -f $c ]] && CONFIGFILE=$c # the last one wins 4328 done 4329 4330 getOptionsFromConfigFile $CONFIGFILE 4331 4332 PARAMETERS=`getopt -l all,allnew,arch:,auto,benchmark,buildtime,checkdeleted,\ 4333 checkfou4s,commonfuncs,config:,end,evaluate,exclude:,exportx:,fixperm,force,\ 4334 getpackagedescriptions,help,host:,import:,interactive,inversecolor,limit-rate:,\ 4335 list,nocache,nocheckdeleted,nocolor,nocompatible,nocont,nodeps,nodownload,\ 4336 nodeltarpms,nogenerated,nogpg,nopatchrpms,noprogress,noproxy,offline,only,\ 4337 product:,proxy:,proxypasswd:,proxyuser:,quiet,remove,safemode,security,server,\ 4338 source:,src:,susepasswd:,susepassword:,suseuser:,suseversion:,testmode,update,\ 4339 upgrade,verbose,version,language:,cleancache,cronserver,cronworkstation,usedir,\ 4340 install,usecurl,use-curl,proxy-digest,noresume,older-than:,acceptpreinstallinfo\ 4341 -o abcdef:ghilnoqrsuvw -n 'fou4s' -- "$@"` 4342 [[ $? -ne 0 ]] && echo "Run fou4s --help for more information" && exit 12 4343 eval checkParameters "$PARAMETERS" # parameter checking 4344 4345 if [[ $EXPORT -eq 1 && $EXPORTFILE == *.tar ]] ; then 4346 if [[ -f $EXPORTFILE ]] ; then 4347 rm "$EXPORTFILE" 4348 #myError 0 "Error: Output file already exists: $EXPORTFILE - aborting" 4349 #exit 13 4350 fi 4351 fi 4352 optionPostProcessing 4353 4354 [[ $CLEANCACHE -eq 1 ]] && cleanCache && exit 4355 4356 if [[ $EXPORT -eq 1 && $EXPORTFILE == *.fou ]] ; then 4357 [[ -f $EXPORTFILE ]] && rm "$EXPORTFILE" 4358 if [[ ! -f $RPMCACHE ]] ; then 4359 updateRpmCache force || (myError 0 "Could not create RPM cache!";exit) 4360 fi 4361 RPMCACHEVERSION==`grep RPMCACHEVERSION $RPMCACHE` 4362 if [[ $RPMCACHEVERSION != $RPMCACHEVER ]] ; then 4363 updateRpmCache force || (myError 0 "Could not update RPM cache!";exit) 4364 fi 4365 cp "$RPMCACHE" "$EXPORTFILE" 4366 gzip "$EXPORTFILE" 4367 mv "$EXPORTFILE.gz" "$EXPORTFILE" 4368 myWarn 0 "Successfully exported machine info to $EXPORTFILE." 4369 myWarn 0 "Please go to internet connected machine and run the following commands there:" 4370 myNote 0 "fou4s --import `basename "$EXPORTFILE"`" 4371 myNote 0 "fou4s -u --host $HOSTNAME --export myExport.tar" 4372 myWarn 0 "Then copy myExport.tar back to this machine and run " 4373 myNote 0 "fou4s --import myExportfile.tar -i" 4374 exit 0 4375 fi 4376 4377 [[ $TESTMODE -eq 1 ]] && myError 0 "*************** USING TEST MODE" 4378 if [[ -n $FORCEDARCH ]] ; then 4379 cleanCache 4380 myEcho 3 "Forcing arch $ARCH to $FORCEDARCH" 4381 ARCH=$FORCEDARCH 4382 fi 4383 updateRpmCache # for faster version comparison 4384 4385 getKernelVersion 4386 4387 if [[ -n $SUSEPRODUCT && $SUSEPRODUCT != */ ]]; then 4388 SUSEPRODUCT=$SUSEPRODUCT/ # append slash 4389 fi 4390 if [[ $VERBOSE -ge 2 ]] ; then 4391 cat <<- _EOF 4392 Using fou4s version $FOUVERSION 4393 Using config file $CONFIGFILE 4394 Using host $HOSTNAME 4395 Using Server(s) $SERVERLIST 4396 Using Arch $ARCH/$MACHINEARCH 4397 Using Valid Archs $VALIDARCHS 4398 Using Product ${SUSEPRODUCT:=SuSE Linux} 4399 Using Version $SUSEVERSION ($NODOTSUSEVERSION) 4400 Using Kernel $KERNELPKG (running: $KERNELVER, installed: $SUSEKERNELVER) 4401 Using Cache/DL-dir $CACHEDIR $DLPATH 4402 _EOF 4403 fi 4404 4405 if [[ $NODOTSUSEVERSION -lt 81 ]] ; then 4406 echo 4407 myError 0 "Sorry! SuSE versions older than 8.1 are no longer supported. Please get fou4s 0.12.6. This is the last version with support for SuSE 7.x and 8.0."| fmt -80 4408 exit 17 4409 fi 4410 #if [[ $NODOTSUSEVERSION -lt 90 ]] ; then 4411 # echo 4412 # myError 0 "Sorry! SuSE versions older than 9.1 are no longer supported. Please get fou4s 0.14.0. This is the last version with support for SuSE 8.x and 9.0."| fmt -80 4413 # exit 17 4414 #fi 4415 4416 # only check for deleted files? 4417 [[ $CHECKONLYDELETED -eq 1 ]] && checkDeleted && exit 4418 4419 for i in /var/adm/YaST/InstSrcManager/IS_CACHE_0x000000*/DATA/descr/packages ; do 4420 [[ -f $i ]] && PACKAGES81="$PACKAGES81 $i" && myEcho 3 "Found SuSE package description file $i" 4421 done 4422 # fix permissions on suse 8.1? This function will exit after being run 4423 [[ $FIXPERMS -eq 1 ]] && fixperms 4424 [[ $GET81PACKAGEDESCRIPTIONS -eq 1 ]] && get81packagedescriptions 4425 [[ $CRONINST -eq 1 ]] && installCronjob 4426 4427 if [[ ! -d $DLPATH ]] ; then 4428 echo "You need to create a directory to store the patches: " 4429 echo "$DLPATH" 4430 echo "(Edit the config file $CONFIGFILE for a different path)" 4431 echo "Exiting ..." 4432 exit 2 4433 fi 4434 4435 # location of gunzipped ARCHIVES.gz 4436 # where gpd.sh finds the ARCHIVES file, to get the package descriptions from 4437 # exported, so get_info_from_ARCHIVES.pl sees it. 4438 set -- $SERVERLIST 4439 SERVERURL=$1 4440 server=${1#@(ftp|http|https|rsync)://} 4441 server=${server%%/*} 4442 server=${server/:*} # strip port number 4443 export ARCHIVES=$DLPATH/$server/$SERVERPATH/ARCHIVES 4444 4445 #used by announcement2pkgdesc and gpd.sh 4446 [[ $COMMONFUNCS -eq 1 ]] && return 4447 doStartupChecks # some initial checks 4448 [[ $UPDATESERVERLIST -eq 1 ]] && updateServerlist && exit 4449 source $RPMCACHE # source the rpm cache 4450 # source the update description cache 4451 SKIPPEDPATCHESFILE=$CACHEDIR/skipped-patches.$HOSTNAME.$SUSEVERSION 4452 AUTOSKIPPEDPATCHESFILE=$CACHEDIR/.cache.$HOSTNAME/skipped-patches.$HOSTNAME.$SUSEVERSION.$LANGUAGE.auto 4453 if [[ $USECACHE -ge 2 && -f $DESCCACHE ]] ; then 4454 myNote 3 "Sourcing description cache" 4455 source $DESCCACHE 4456 if [[ $DESCRIPTIONCACHE_VERSION != 1.4 || $DC_ARCH != $ARCH || \ 4457 $DC_PRODUCT != $SUSEPRODUCT || $DC_VERSION != $SUSEVERSION || \ 4458 $DC_SERVERLIST != $SERVERLIST || $DC_LANGUAGE != $LANGUAGE || \ 4459 $SKIPPEDPATCHESFILE -nt $AUTOSKIPPEDPATCHESFILE ]] ; then 4460 myEcho 2 "Removing autoskipped-patches because description cache is invalid!" 4461 rm -f $AUTOSKIPPEDPATCHESFILE $DESCCACHE 4462 # unset all found packages 4463 for i in `echo ${!longdesc_*} ${!license_*} ${!shortdesc_*} ${!packageinfo_*} ${!package_*} ${!dlfile1_*} ${!server1_*}` ; do 4464 unset $i 4465 done 4466 fi 4467 fi 4468 if [[ $RPMCACHEVERSION != $RPMCACHEVER || $RPMCACHECOMPLETE != 1 || -z $pkg_bash ]] ; then 4469 updateRpmCache force 4470 myNote 3 "Sourcing RPM DB cache" 4471 source $RPMCACHE 4472 if [[ $RPMCACHEVERSION != $RPMCACHEVER || $RPMCACHECOMPLETE != 1 ]] ; then 4473 myError 0 "BUG! updateRpmCache failed twice without obvious reason." 4474 exit 13 4475 fi 4476 fi 4477 [[ $INTERACTIVE -eq 1 ]] && exec 6<&0 # copy stdin 4478 4479 if [[ $NODOTSUSEVERSION -ge 110 ]] && [ -f $SKIPPEDPATCHESFILE ] ; then 4480 while read line; do 4481 EXCLUDELIST="$EXCLUDELIST $line" 4482 done < $SKIPPEDPATCHESFILE 4483 EXCLUDELIST=${EXCLUDELIST## } 4484 listsToPatterns EXCLUDELIST 4485 fi 4486 4487 processServerList # find updates from all servers 4488 if [ $USECACHE -ge 2 ] ; then # update cache with found updates 4489 updateDescriptionCache 4490 printf "%s\n" $ALLPKGDESCFILES > $AUTOSKIPPEDPATCHESFILE 4491 # strip blank lines: 4492 grep -v "^$" $AUTOSKIPPEDPATCHESFILE 2>/dev/null > \ 4493 $AUTOSKIPPEDPATCHESFILE.new && \ 4494 mv $AUTOSKIPPEDPATCHESFILE.new $AUTOSKIPPEDPATCHESFILE 4495 fi 4496 if [[ $CHECKONLY -eq 1 || $DOINSTALL -eq 1 ]] ; then 4497 processFoundUpdates # shows them on the screen and installs 4498 fi 4499 cd "$BASEDIR" 4500 cd "$DLPATH" 4501 [[ -n $RPMINSTLIST ]] && rpmInstall $RPMINSTLIST 4502 4503 if [[ $CHECKONLY -eq 1 && $QUIET -eq 0 && ${COUNTER[_ALL]} -gt 0 && $DOWNLOAD -eq 0 || $LISTAVAILRPMS -eq 1 ]] ; then 4504 showSummary 4505 echo This run of fou4s took $SECONDS secs. # $SECONDS is from BASH! 4506 [[ -n $COL_BLACK && $INVERSE -eq 0 ]] && echo -e "${COL_BLACK}*** IF YOU CAN READ THIS, try fou4s --inversecolor or set InverseColor=1 ***$COL_NORM" 4507 fi 4508 if [[ $AUTOMODE -eq 1 && $DOWNLOAD -eq 1 ]] ; then 4509 if [[ $((COUNTER[_ALL]-COUNTER[_INST])) -gt 0 ]] ; then 4510 [[ $USEBUILDTIME -eq 1 ]] && b=" --buildtime" || b= 4511 showSummary 4512 echo 4513 echo "Please run fou4s -i$b now, to install the downloaded packages." 4514 echo This run of fou4s $FOUVERSION took $SECONDS secs. 4515 logWrite 1 "Found ${COUNTER[_ALL]} update(s) (fou4s $FOUVERSION)" 4516 elif [[ ${COUNTER[_ALL]} -gt 0 ]] ; then 4517 echo This run of fou4s took $SECONDS secs. 4518 fi 4519 fi 4520 4521 if [[ $EXPORT -eq 1 ]] ; then 4522 myNote 0 "Successfully exported to `basename $EXPORTFILE`" 4523 fi 4524 4525 if [[ $DOINSTALL -eq 1 && $SUSECONFIG -eq 2 ]] ; then 4526 [[ $TESTMODE -eq 1 ]] && myError 0 "Testmode - NOT running SuSEconfig" || \ 4527 if [[ $EUID -eq 0 ]] ; then 4528 myWarn 0 "Running SuSEconfig ..." 4529 sg root -c /sbin/SuSEconfig 4530 else 4531 myError 0 "Error: You must be root to run SuSEconfig!" 4532 fi 4533 fi 4534 4535 # check for deleted files (by RPM) that are still in use 4536 [[ $CHECKDELETED -eq 1 ]] && checkDeleted 4537 4538 if [[ $FAILCOUNT -gt 0 ]] ; then 4539 myWarn 0 "Warning: $FAILCOUNT updates failed. Please fix the problems and try again" 4540 fi 4541 exit 0 4542 # vim: set ai ts=3 sw=3 is :