1#!/bin/sh 2# ipkg - the itsy package management system 3# 4# Copyright (C) 2001 Carl D. Worth 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2, or (at your option) 9# any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16 17set -e 18 19# By default do not do globbing. Any command wanting globbing should 20# explicitly enable it first and disable it afterwards. 21set -o noglob 22 23ipkg_is_upgrade () { 24 local A B a b 25 A=$(echo $1 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g"). 26 B=$(echo $2 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g"). 27 while [ \! -z "$A" ] && [ \! -z "$B" ]; do { 28 set $A; a=$1; shift; A=$* 29 set $B; b=$1; shift; B=$* 30 [ "$a" -lt "$b" ] 2>&- && return 1 31 { [ "$a" -gt "$b" ] 2>&- || [ "$a" ">" "$b" ]; } && return 32 }; done 33 return 1 34} 35 36ipkg_srcs() { 37 local srcre="$1" 38 sed -ne "s/^src[[:space:]]\+$srcre[[:space:]]\+//p" < $IPKG_CONF 39} 40 41ipkg_src_names() { 42 sed -ne "s/^src[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF 43} 44 45ipkg_src_byname() { 46 local src="$1" 47 ipkg_srcs $src | head -n 1 48} 49 50ipkg_dests() { 51 local destre="`echo $1 | ipkg_protect_slashes`" 52 sed -ne "/^dest[[:space:]]\+$destre/{ 53s/^dest[[:space:]]\+[^[:space:]]\+[[:space:]]\+// 54s/^/`echo $IPKG_OFFLINE_ROOT | ipkg_protect_slashes`/ 55p 56}" < $IPKG_CONF 57} 58 59ipkg_dest_names() { 60 sed -ne "s/^dest[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF 61} 62 63ipkg_dests_all() { 64 ipkg_dests '.*' 65} 66 67ipkg_state_dirs() { 68 ipkg_dests_all | sed "s|\$|/$IPKG_DIR_PREFIX|" 69} 70 71ipkg_dest_default() { 72 ipkg_dests_all | head -n 1 73} 74 75ipkg_dest_default_name() { 76 ipkg_dest_names | head -n 1 77} 78 79ipkg_dest_byname() { 80 local dest="$1" 81 ipkg_dests $dest | head -n 1 82} 83 84ipkg_option() { 85 local option="$1" 86 sed -ne "s/^option[[:space:]]\+$option[[:space:]]\+//p" < $IPKG_CONF 87} 88 89ipkg_load_configuration() { 90 if [ -z "$IPKG_CONF_DIR" ]; then 91 IPKG_CONF_DIR=/etc 92 fi 93 94 IPKG_CONF="$IPKG_CONF_DIR/ipkg.conf" 95 96 if [ -z "$IPKG_OFFLINE_ROOT" ]; then 97 IPKG_OFFLINE_ROOT="`ipkg_option offline_root`" 98 fi 99 # Export IPKG_OFFLINE_ROOT for use by update-alternatives 100 export IPKG_OFFLINE_ROOT 101 if [ -n "$DEST_NAME" ]; then 102 IPKG_ROOT="`ipkg_dest_byname $DEST_NAME`" 103 if [ -z "$IPKG_ROOT" ]; then 104 if [ -d "$IPKG_OFFLINE_ROOT$DEST_NAME" ]; then 105 IPKG_ROOT="$IPKG_OFFLINE_ROOT$DEST_NAME"; 106 else 107 echo "ipkg: invalid destination specification: $DEST_NAME 108Valid destinations are directories or one of the dest names from $IPKG_CONF:" >&2 109 ipkg_dest_names >&2 110 return 1 111 fi 112 fi 113 else 114 IPKG_ROOT="`ipkg_dest_default`" 115 fi 116 117 # Global ipkg state directories 118 IPKG_DIR_PREFIX=opt/usr/lib/ipkg 119 IPKG_LISTS_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/lists 120 IPKG_PENDING_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/pending 121 if [ -z "$IPKG_TMP" ]; then 122 IPKG_TMP=$IPKG_ROOT/tmp/ipkg 123 fi 124 125 [ -e "$IPKG_TMP" ] || mkdir -p $IPKG_TMP 126 127 # Destination specific ipkg meta-data directory 128 IPKG_STATE_DIR=$IPKG_ROOT/$IPKG_DIR_PREFIX 129 130 # Proxy Support 131 IPKG_PROXY_USERNAME="`ipkg_option proxy_username`" 132 IPKG_PROXY_PASSWORD="`ipkg_option proxy_password`" 133 IPKG_HTTP_PROXY="`ipkg_option http_proxy`" 134 IPKG_FTP_PROXY="`ipkg_option ftp_proxy`" 135 IPKG_NO_PROXY="`ipkg_option no_proxy`" 136 if [ -n "$IPKG_HTTP_PROXY" ]; then 137 export http_proxy="$IPKG_HTTP_PROXY" 138 fi 139 140 if [ -n "$IPKG_FTP_PROXY" ]; then 141 export ftp_proxy="$IPKG_FTP_PROXY" 142 fi 143 144 if [ -n "$IPKG_NO_PROXY" ]; then 145 export no_proxy="$IPKG_NO_PROXY" 146 fi 147 148 IPKG_STATUS_FIELDS='\(Package\|Status\|Essential\|Version\|Conffiles\|Root\)' 149} 150 151ipkg_usage() { 152 [ $# -gt 0 ] && echo "ipkg: $*" 153 echo " 154usage: ipkg [options...] sub-command [arguments...] 155where sub-command is one of: 156 157Package Manipulation: 158 update Update list of available packages 159 upgrade Upgrade all installed packages to latest version 160 install <pkg> Download and install <pkg> (and dependencies) 161 install <file.ipk> Install package <file.ipk> 162 install <file.deb> Install package <file.deb> 163 remove <pkg> Remove package <pkg> 164 165Informational Commands: 166 list List available packages and descriptions 167 files <pkg> List all files belonging to <pkg> 168 search <file> Search for a packaging providing <file> 169 info [pkg [<field>]] Display all/some info fields for <pkg> or all 170 status [pkg [<field>]] Display all/some status fields for <pkg> or all 171 depends <pkg> Print uninstalled package dependencies for <pkg> 172 173Options: 174 -d <dest_name> Use <dest_name> as the the root directory for 175 -dest <dest_name> package installation, removal, upgrading. 176 <dest_name> should be a defined dest name from the 177 configuration file, (but can also be a directory 178 name in a pinch). 179 -o <offline_root> Use <offline_root> as the root for offline installation. 180 -offline <offline_root> 181 182Force Options (use when ipkg is too smart for its own good): 183 -force-depends Make dependency checks warnings instead of errors 184 -force-defaults Use default options for questions asked by ipkg. 185 (no prompts). Note that this will not prevent 186 package installation scripts from prompting. 187" >&2 188 exit 1 189} 190 191ipkg_dir_part() { 192 local dir="`echo $1 | sed -ne 's/\(.*\/\).*/\1/p'`" 193 if [ -z "$dir" ]; then 194 dir="./" 195 fi 196 echo $dir 197} 198 199ipkg_file_part() { 200 echo $1 | sed 's/.*\///' 201} 202 203ipkg_protect_slashes() { 204 sed -e 's/\//\\\//g' 205} 206 207ipkg_download() { 208 local src="$1" 209 local dest="$2" 210 211 local src_file="`ipkg_file_part $src`" 212 local dest_dir="`ipkg_dir_part $dest`" 213 if [ -z "$dest_dir" ]; then 214 dest_dir="$IPKG_TMP" 215 fi 216 217 local dest_file="`ipkg_file_part $dest`" 218 if [ -z "$dest_file" ]; then 219 dest_file="$src_file" 220 fi 221 222 # Proxy support 223 local proxyuser="" 224 local proxypassword="" 225 local proxyoption="" 226 227 if [ -n "$IPKG_PROXY_USERNAME" ]; then 228 proxyuser="--proxy-user=\"$IPKG_PROXY_USERNAME\"" 229 proxypassword="--proxy-passwd=\"$IPKG_PROXY_PASSWORD\"" 230 fi 231 232 if [ -n "$IPKG_PROXY_HTTP" -o -n "$IPKG_PROXY_FTP" ]; then 233 proxyoption="--proxy=on" 234 fi 235 236 echo "Downloading $src ..." 237 rm -f $IPKG_TMP/$src_file 238 case "$src" in 239 http://* | ftp://*) 240 if ! wget $proxyoption $proxyuser $proxypassword -P $IPKG_TMP $src; then 241 echo "ipkg_download: ERROR: Failed to retrieve $src, returning $err" 242 return 1 243 fi 244 mv $IPKG_TMP/$src_file $dest_dir/$dest_file 2>/dev/null 245 ;; 246 file:/* ) 247 ln -s `echo $src | sed 's/^file://'` $dest_dir/$dest_file 2>/dev/null 248 ;; 249 *) 250 echo "DEBUG: $src" 251 ;; 252 esac 253 254 echo "Done." 255 return 0 256} 257 258ipkg_update() { 259 if [ ! -e "$IPKG_LISTS_DIR" ]; then 260 mkdir -p $IPKG_LISTS_DIR 261 fi 262 263 local err= 264 for src_name in `ipkg_src_names`; do 265 local src="`ipkg_src_byname $src_name`" 266 if ! ipkg_download $src/Packages $IPKG_LISTS_DIR/$src_name; then 267 echo "ipkg_update: Error downloading $src/Packages to $IPKG_LISTS_DIR/$src_name" >&2 268 err=t 269 else 270 echo "Updated list of available packages in $IPKG_LISTS_DIR/$src_name" 271 fi 272 done 273 274 [ -n "$err" ] && return 1 275 276 return 0 277} 278 279ipkg_list() { 280 for src in `ipkg_src_names`; do 281 if ipkg_require_list $src; then 282# black magic... 283sed -ne " 284/^Package:/{ 285s/^Package:[[:space:]]*\<\([a-z0-9.+-]*$1[a-z0-9.+-]*\).*/\1/ 286h 287} 288/^Description:/{ 289s/^Description:[[:space:]]*\(.*\)/\1/ 290H 291g 292s/\\ 293/ - / 294p 295} 296" $IPKG_LISTS_DIR/$src 297 fi 298 done 299} 300 301ipkg_extract_paragraph() { 302 local pkg="$1" 303 sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/p" 304} 305 306ipkg_extract_field() { 307 local field="$1" 308# blacker magic... 309 sed -ne " 310: TOP 311/^$field:/{ 312p 313n 314b FIELD 315} 316d 317: FIELD 318/^$/b TOP 319/^[^[:space:]]/b TOP 320p 321n 322b FIELD 323" 324} 325 326ipkg_extract_value() { 327 sed -e "s/^[^:]*:[[:space:]]*//" 328} 329 330ipkg_require_list() { 331 [ $# -lt 1 ] && return 1 332 local src="$1" 333 if [ ! -f "$IPKG_LISTS_DIR/$src" ]; then 334 echo "ERROR: File not found: $IPKG_LISTS_DIR/$src" >&2 335 echo " You probably want to run \`ipkg update'" >&2 336 return 1 337 fi 338 return 0 339} 340 341ipkg_info() { 342 for src in `ipkg_src_names`; do 343 if ipkg_require_list $src; then 344 case $# in 345 0) 346 cat $IPKG_LISTS_DIR/$src 347 ;; 348 1) 349 ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src 350 ;; 351 *) 352 ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src | ipkg_extract_field $2 353 ;; 354 esac 355 fi 356 done 357} 358 359ipkg_status_sd() { 360 [ $# -lt 1 ] && return 0 361 sd="$1" 362 shift 363 if [ -f $sd/status ]; then 364 case $# in 365 0) 366 cat $sd/status 367 ;; 368 1) 369 ipkg_extract_paragraph $1 < $sd/status 370 ;; 371 *) 372 ipkg_extract_paragraph $1 < $sd/status | ipkg_extract_field $2 373 ;; 374 esac 375 fi 376 return 0 377} 378 379ipkg_status_all() { 380 for sd in `ipkg_state_dirs`; do 381 ipkg_status_sd $sd $* 382 done 383} 384 385ipkg_status() { 386 if [ -n "$DEST_NAME" ]; then 387 ipkg_status_sd $IPKG_STATE_DIR $* 388 else 389 ipkg_status_all $* 390 fi 391} 392 393ipkg_status_matching_sd() { 394 local sd="$1" 395 local re="$2" 396 if [ -f $sd/status ]; then 397 sed -ne " 398: TOP 399/^Package:/{ 400s/^Package:[[:space:]]*// 401s/[[:space:]]*$// 402h 403} 404/$re/{ 405g 406p 407b NEXT 408} 409d 410: NEXT 411/^$/b TOP 412n 413b NEXT 414" < $sd/status 415 fi 416 return 0 417} 418 419ipkg_status_matching_all() { 420 for sd in `ipkg_state_dirs`; do 421 ipkg_status_matching_sd $sd $* 422 done 423} 424 425ipkg_status_matching() { 426 if [ -n "$DEST_NAME" ]; then 427 ipkg_status_matching_sd $IPKG_STATE_DIR $* 428 else 429 ipkg_status_matching_all $* 430 fi 431} 432 433ipkg_status_installed_sd() { 434 local sd="$1" 435 local pkg="$2" 436 ipkg_status_sd $sd $pkg Status | grep -q "Status: install ok installed" 437} 438 439ipkg_status_installed_all() { 440 local ret=1 441 for sd in `ipkg_state_dirs`; do 442 if `ipkg_status_installed_sd $sd $*`; then 443 ret=0 444 fi 445 done 446 return $ret 447} 448 449ipkg_status_mentioned_sd() { 450 local sd="$1" 451 local pkg="$2" 452 [ -n "`ipkg_status_sd $sd $pkg Status`" ] 453} 454 455ipkg_files() { 456 local pkg="$1" 457 if [ -n "$DEST_NAME" ]; then 458 dests=$IPKG_ROOT 459 else 460 dests="`ipkg_dests_all`" 461 fi 462 for dest in $dests; do 463 if [ -f $dest/$IPKG_DIR_PREFIX/info/$pkg.list ]; then 464 dest_sed="`echo $dest | ipkg_protect_slashes`" 465 sed -e "s/^/$dest_sed/" < $dest/$IPKG_DIR_PREFIX/info/$pkg.list 466 fi 467 done 468} 469 470ipkg_search() { 471 local pattern="$1" 472 473 for dest_name in `ipkg_dest_names`; do 474 dest="`ipkg_dest_byname $dest_name`" 475 dest_sed="`echo $dest | ipkg_protect_slashes`" 476 477 set +o noglob 478 local list_files="`ls -1 $dest/$IPKG_DIR_PREFIX/info/*.list 2>/dev/null`" 479 set -o noglob 480 for file in $list_files; do 481 if sed "s/^/$dest_sed/" $file | grep -q $pattern; then 482 local pkg="`echo $file | sed "s/^.*\/\(.*\)\.list/\1/"`" 483 [ "$dest_name" != `ipkg_dest_default_name` ] && pkg="$pkg ($dest_name)" 484 sed "s/^/$dest_sed/" $file | grep $pattern | sed "s/^/$pkg: /" 485 fi 486 done 487 done 488} 489 490ipkg_status_remove_sd() { 491 local sd="$1" 492 local pkg="$2" 493 494 if [ ! -f $sd/status ]; then 495 mkdir -p $sd 496 touch $sd/status 497 fi 498 sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/!p" < $sd/status > $sd/status.new 499 mv $sd/status.new $sd/status 500} 501 502ipkg_status_remove_all() { 503 for sd in `ipkg_state_dirs`; do 504 ipkg_status_remove_sd $sd $* 505 done 506} 507 508ipkg_status_remove() { 509 if [ -n "$DEST_NAME" ]; then 510 ipkg_status_remove_sd $IPKG_STATE_DIR $* 511 else 512 ipkg_status_remove_all $* 513 fi 514} 515 516ipkg_status_update_sd() { 517 local sd="$1" 518 local pkg="$2" 519 520 ipkg_status_remove_sd $sd $pkg 521 ipkg_extract_field "$IPKG_STATUS_FIELDS" >> $sd/status 522 echo "" >> $sd/status 523} 524 525ipkg_status_update() { 526 ipkg_status_update_sd $IPKG_STATE_DIR $* 527} 528 529ipkg_unsatisfied_dependences() { 530 local pkg=$1 531 local deps="`ipkg_get_depends $pkg`" 532 local remaining_deps= 533 for dep in $deps; do 534 local installed="`ipkg_get_installed $dep`" 535 if [ "$installed" != "installed" ] ; then 536 remaining_deps="$remaining_deps $dep" 537 fi 538 done 539 ## echo "ipkg_unsatisfied_dependences pkg=$pkg $remaining_deps" > /dev/console 540 echo $remaining_deps 541} 542 543ipkg_safe_pkg_name() { 544 local pkg=$1 545 local spkg="`echo pkg_$pkg | sed -e y/-+./___/`" 546 echo $spkg 547} 548 549ipkg_set_depends() { 550 local pkg=$1; shift 551 local new_deps="$*" 552 pkg="`ipkg_safe_pkg_name $pkg`" 553 ## setvar ${pkg}_depends "$new_deps" 554 echo $new_deps > $IPKG_TMP/${pkg}.depends 555} 556 557ipkg_get_depends() { 558 local pkg=$1 559 pkg="`ipkg_safe_pkg_name $pkg`" 560 cat $IPKG_TMP/${pkg}.depends 561 ## eval "echo \$${pkg}_depends" 562} 563 564ipkg_set_installed() { 565 local pkg=$1 566 pkg="`ipkg_safe_pkg_name $pkg`" 567 echo installed > $IPKG_TMP/${pkg}.installed 568 ## setvar ${pkg}_installed "installed" 569} 570 571ipkg_set_uninstalled() { 572 local pkg=$1 573 pkg="`ipkg_safe_pkg_name $pkg`" 574 ### echo ipkg_set_uninstalled $pkg > /dev/console 575 echo uninstalled > $IPKG_TMP/${pkg}.installed 576 ## setvar ${pkg}_installed "uninstalled" 577} 578 579ipkg_get_installed() { 580 local pkg=$1 581 pkg="`ipkg_safe_pkg_name $pkg`" 582 if [ -f $IPKG_TMP/${pkg}.installed ]; then 583 cat $IPKG_TMP/${pkg}.installed 584 fi 585 ## eval "echo \$${pkg}_installed" 586} 587 588ipkg_depends() { 589 local new_pkgs="$*" 590 local all_deps= 591 local installed_pkgs="`ipkg_status_matching_all 'Status:.*[[:space:]]installed'`" 592 for pkg in $installed_pkgs; do 593 ipkg_set_installed $pkg 594 done 595 while [ -n "$new_pkgs" ]; do 596 all_deps="$all_deps $new_pkgs" 597 local new_deps= 598 for pkg in $new_pkgs; do 599 if echo $pkg | grep -q '[^a-z0-9.+-]'; then 600 echo "ipkg_depends: ERROR: Package name $pkg contains illegal characters (should be [a-z0-9.+-])" >&2 601 return 1 602 fi 603 # TODO: Fix this. For now I am ignoring versions and alternations in dependencies. 604 new_deps="$new_deps "`ipkg_info $pkg '\(Pre-\)\?Depends' | ipkg_extract_value | sed -e 's/([^)]*)//g 605s/\(|[[:space:]]*[a-z0-9.+-]\+[[:space:]]*\)\+//g 606s/,/ /g 607s/ \+/ /g'` 608 ipkg_set_depends $pkg $new_deps 609 done 610 611 new_deps=`echo $new_deps | sed -e 's/[[:space:]]\+/\n/g' | sort -u` 612 613 local maybe_new_pkgs= 614 for pkg in $new_deps; do 615 if ! echo $installed_pkgs | grep -q "\<$pkg\>"; then 616 maybe_new_pkgs="$maybe_new_pkgs $pkg" 617 fi 618 done 619 620 new_pkgs= 621 for pkg in $maybe_new_pkgs; do 622 if ! echo $all_deps | grep -q "\<$pkg\>"; then 623 if [ -z "`ipkg_info $pkg`" ]; then 624 echo "ipkg_depends: Warning: $pkg mentioned in dependency but no package found in $IPKG_LISTS_DIR" >&2 625 ipkg_set_installed $pkg 626 else 627 new_pkgs="$new_pkgs $pkg" 628 ipkg_set_uninstalled $pkg 629 fi 630 else 631 ipkg_set_uninstalled $pkg 632 fi 633 done 634 done 635 636 echo $all_deps 637} 638 639ipkg_get_install_dest() { 640 local dest="$1" 641 shift 642 local sd=$dest/$IPKG_DIR_PREFIX 643 local info_dir=$sd/info 644 645 local requested_pkgs="$*" 646 local pkgs="`ipkg_depends $*`" 647 648 mkdir -p $info_dir 649 for pkg in $pkgs; do 650 if ! ipkg_status_mentioned_sd $sd $pkg; then 651 echo "Package: $pkg 652Status: install ok not-installed" | ipkg_status_update_sd $sd $pkg 653 fi 654 done 655 ## mark the packages that we were directly requested to install as uninstalled 656 for pkg in $requested_pkgs; do ipkg_set_uninstalled $pkg; done 657 658 local new_pkgs= 659 local pkgs_installed=0 660 while [ -n "pkgs" ]; do 661 curcheck=0 662 ## echo "pkgs to install: {$pkgs}" > /dev/console 663 for pkg in $pkgs; do 664 curcheck="`expr $curcheck + 1`" 665 local is_installed="`ipkg_get_installed $pkg`" 666 if [ "$is_installed" = "installed" ]; then 667 echo "$pkg is installed" > /dev/console 668 continue 669 fi 670 671 local remaining_deps="`ipkg_unsatisfied_dependences $pkg`" 672 if [ -n "$remaining_deps" ]; then 673 new_pkgs="$new_pkgs $pkg" 674 ### echo "Dependences not satisfied for $pkg: $remaining_deps" 675 if [ $curcheck -ne `echo $pkgs|wc -w` ]; then 676 continue 677 fi 678 fi 679 680 local filename= 681 for src in `ipkg_src_names`; do 682 if ipkg_require_list $src; then 683 filename="`ipkg_extract_paragraph $pkg < $IPKG_LISTS_DIR/$src | ipkg_extract_field Filename | ipkg_extract_value`" 684 [ -n "$filename" ] && break 685 fi 686 done 687 688 if [ -z "$filename" ]; then 689 echo "ipkg_get_install: ERROR: Cannot find package $pkg in $IPKG_LISTS_DIR" 690 echo "ipkg_get_install: Check the spelling and maybe run \`ipkg update'." 691 ipkg_status_remove_sd $sd $pkg 692 return 1; 693 fi 694 695 echo "" 696 local tmp_pkg_file="$IPKG_TMP/"`ipkg_file_part $filename` 697 if ! ipkg_download `ipkg_src_byname $src`/$filename $tmp_pkg_file; then 698 echo "ipkg_get_install: Perhaps you need to run \`ipkg update'?" 699 return 1 700 fi 701 702 if ! ipkg_install_file_dest $dest $tmp_pkg_file; then 703 echo "ipkg_get_install: ERROR: Failed to install $tmp_pkg_file" 704 echo "ipkg_get_install: I'll leave it there for you to try a manual installation" 705 return 1 706 fi 707 708 ipkg_set_installed $pkg 709 pkgs_installed="`expr $pkgs_installed + 1`" 710 rm $tmp_pkg_file 711 done 712 ### echo "Installed $pkgs_installed package(s) this round" 713 if [ $pkgs_installed -eq 0 ]; then 714 if [ -z "$new_pkgs" ]; then 715 break 716 fi 717 fi 718 pkgs_installed=0 719 pkgs="$new_pkgs" 720 new_pkgs= 721 curcheck=0 722 done 723} 724 725ipkg_get_install() { 726 ipkg_get_install_dest $IPKG_ROOT $* 727} 728 729ipkg_install_file_dest() { 730 local dest="$1" 731 local filename="$2" 732 local sd=$dest/$IPKG_DIR_PREFIX 733 local info_dir=$sd/info 734 735 if [ ! -f "$filename" ]; then 736 echo "ipkg_install_file: ERROR: File $filename not found" 737 return 1 738 fi 739 740 local pkg="`ipkg_file_part $filename | sed 's/\([a-z0-9.+-]\+\)_.*/\1/'`" 741 local ext="`echo $filename | sed 's/.*\.//'`" 742 local pkg_extract_stdout 743 if [ "$ext" = "ipk" ]; then 744 pkg_extract_stdout="tar -xzOf" 745 elif [ "$ext" = "deb" ]; then 746 pkg_extract_stdout="ar p" 747 else 748 echo "ipkg_install_file: ERROR: File $filename has unknown extension $ext (not .ipk or .deb)" 749 return 1 750 fi 751 752 # Check dependencies 753 local depends="`ipkg_depends $pkg | sed -e "s/\<$pkg\>//"`" 754 755 # Don't worry about deps that are scheduled for installation 756 local missing_deps= 757 for dep in $depends; do 758 if ! ipkg_status_all $dep | grep -q 'Status:[[:space:]]install'; then 759 missing_deps="$missing_deps $dep" 760 fi 761 done 762 763 if [ ! -z "$missing_deps" ]; then 764 if [ -n "$FORCE_DEPENDS" ]; then 765 echo "ipkg_install_file: Warning: $pkg depends on the following uninstalled programs: $missing_deps" 766 else 767 echo "ipkg_install_file: ERROR: $pkg depends on the following uninstalled programs: 768 $missing_deps" 769 echo "ipkg_install_file: You may want to use \`ipkg install' to install these." 770 return 1 771 fi 772 fi 773 774 mkdir -p $IPKG_TMP/$pkg/control 775 mkdir -p $IPKG_TMP/$pkg/data 776 mkdir -p $info_dir 777 778 if ! $pkg_extract_stdout $filename ./control.tar.gz | (cd $IPKG_TMP/$pkg/control; tar -xzf - ) ; then 779 echo "ipkg_install_file: ERROR unpacking control.tar.gz from $filename" 780 return 1 781 fi 782 783 if [ -n "$IPKG_OFFLINE_ROOT" ]; then 784 if grep -q '^InstallsOffline:[[:space:]]*no' $IPKG_TMP/$pkg/control/control; then 785 echo "*** Warning: Package $pkg may not be installed in offline mode" 786 echo "*** Warning: Scheduling $filename for pending installation (installing into $IPKG_PENDING_DIR)" 787 echo "Package: $pkg 788Status: install ok pending" | ipkg_status_update_sd $sd $pkg 789 mkdir -p $IPKG_PENDING_DIR 790 cp -f $filename $IPKG_PENDING_DIR 791 rm -r $IPKG_TMP/$pkg/control 792 rm -r $IPKG_TMP/$pkg/data 793 rmdir $IPKG_TMP/$pkg 794 return 0 795 fi 796 fi 797 798 799 echo -n "Unpacking $pkg..." 800 set +o noglob 801 for file in $IPKG_TMP/$pkg/control/*; do 802 local base_file="`ipkg_file_part $file`" 803 mv $file $info_dir/$pkg.$base_file 804 done 805 set -o noglob 806 rm -r $IPKG_TMP/$pkg/control 807 808 if ! $pkg_extract_stdout $filename ./data.tar.gz | (cd $IPKG_TMP/$pkg/data; tar -xzf - ) ; then 809 echo "ipkg_install_file: ERROR unpacking data.tar.gz from $filename" 810 return 1 811 fi 812 echo "Done." 813 814 echo -n "Configuring $pkg..." 815 export PKG_ROOT=$dest 816 if [ -x "$info_dir/$pkg.preinst" ]; then 817 if ! $info_dir/$pkg.preinst install; then 818 echo "$info_dir/$pkg.preinst failed. Aborting installation of $pkg" 819 rm -rf $IPKG_TMP/$pkg/data 820 rmdir $IPKG_TMP/$pkg 821 return 1 822 fi 823 fi 824 825 local old_conffiles="`ipkg_status_sd $sd $pkg Conffiles | ipkg_extract_value`" 826 local new_conffiles= 827 if [ -f "$info_dir/$pkg.conffiles" ]; then 828 for conffile in `cat $info_dir/$pkg.conffiles`; do 829 if [ -f "$dest/$conffile" ] && ! echo " $old_conffiles " | grep -q " $conffile "`md5sum $dest/$conffile | sed 's/ .*//'`; then 830 local use_maintainers_conffile= 831 if [ -z "$FORCE_DEFAULTS" ]; then 832 while true; do 833 echo -n "Configuration file \`$conffile' 834 ==> File on system created by you or by a script. 835 ==> File also in package provided by package maintainer. 836 What would you like to do about it ? Your options are: 837 Y or I : install the package maintainer's version 838 N or O : keep your currently-installed version 839 D : show the differences between the versions (if diff is installed) 840 The default action is to keep your current version. 841*** `ipkg_file_part $conffile` (Y/I/N/O/D) [default=N] ? " 842 read response 843 case "$response" in 844 [YyIi] | [Yy][Ee][Ss]) 845 use_maintainers_conffile=t 846 break 847 ;; 848 [Dd]) 849 echo " 850diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile" 851 diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile || true 852 echo "[Press ENTER to continue]" 853 read junk 854 ;; 855 *) 856 break 857 ;; 858 esac 859 done 860 fi 861 if [ -n "$use_maintainers_conffile" ]; then 862 local md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`" 863 new_conffiles="$new_conffiles $conffile $md5sum" 864 else 865 new_conffiles="$new_conffiles $conffile <custom>" 866 rm $IPKG_TMP/$pkg/data/$conffile 867 fi 868 else 869 md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`" 870 new_conffiles="$new_conffiles $conffile $md5sum" 871 fi 872 done 873 fi 874 875 local owd="`pwd`" 876 (cd $IPKG_TMP/$pkg/data/; tar cf - . | (cd $owd; cd $dest; tar xf -)) 877 rm -rf $IPKG_TMP/$pkg/data 878 rmdir $IPKG_TMP/$pkg 879 rm -f $info_dir/$pkg.list 880 $pkg_extract_stdout $filename ./data.tar.gz | tar tzf - | sed -e 's/^\.//' > $info_dir/$pkg.list 881 882 if [ -x "$info_dir/$pkg.postinst" ]; then 883 $info_dir/$pkg.postinst configure 884 fi 885 886 if [ -n "$new_conffiles" ]; then 887 new_conffiles='Conffiles: '`echo $new_conffiles | ipkg_protect_slashes` 888 fi 889 local sed_safe_offline_root="`echo ${IPKG_OFFLINE_ROOT} | ipkg_protect_slashes`" 890 local sed_safe_root="`echo $dest | sed -e "s/^${sed_safe_offline_root}//" | ipkg_protect_slashes`" 891 sed -e "s/\(Package:.*\)/\1\\ 892Status: install ok installed\\ 893Root: ${sed_safe_root}\\ 894${new_conffiles}/" $info_dir/$pkg.control | ipkg_status_update_sd $sd $pkg 895 896 rm -f $info_dir/$pkg.control 897 rm -f $info_dir/$pkg.conffiles 898 rm -f $info_dir/$pkg.preinst 899 rm -f $info_dir/$pkg.postinst 900 901 echo "Done." 902} 903 904ipkg_install_file() { 905 ipkg_install_file_dest $IPKG_ROOT $* 906} 907 908ipkg_install() { 909 910 while [ $# -gt 0 ]; do 911 local pkg="$1" 912 shift 913 914 case "$pkg" in 915 http://* | ftp://*) 916 local tmp_pkg_file="$IPKG_TMP/"`ipkg_file_part $pkg` 917 if ipkg_download $pkg $tmp_pkg_file; then 918 ipkg_install_file $tmp_pkg_file 919 rm $tmp_pkg_file 920 fi 921 ;; 922 file:/*.ipk | file://*.deb) 923 local ipkg_filename="`echo $pkg|sed 's/^file://'`" 924 ipkg_install_file $ipkg_filename 925 ;; 926 *.ipk | *.deb) 927 ipkg_install_file $pkg 928 ;; 929 *) 930 ipkg_get_install $pkg || true 931 ;; 932 esac 933 done 934} 935 936ipkg_install_pending() { 937 [ -n "$IPKG_OFFLINE_ROOT" ] && return 0 938 939 if [ -d "$IPKG_PENDING_DIR" ]; then 940 set +o noglob 941 local pending="`ls -1d $IPKG_PENDING_DIR/*.ipk 2> /dev/null`" || true 942 set -o noglob 943 if [ -n "$pending" ]; then 944 echo "The following packages in $IPKG_PENDING_DIR will now be installed:" 945 echo $pending 946 for filename in $pending; do 947 if ipkg_install_file $filename; then 948 rm $filename 949 fi 950 done 951 fi 952 fi 953 return 0 954} 955 956ipkg_install_wanted() { 957 local wanted="`ipkg_status_matching 'Status:[[:space:]]*install.*not-installed'`" 958 959 if [ -n "$wanted" ]; then 960 echo "The following package were previously requested but have not been installed:" 961 echo $wanted 962 963 if [ -n "$FORCE_DEFAULTS" ]; then 964 echo "Installing them now." 965 else 966 echo -n "Install them now [Y/n] ? " 967 read response 968 case "$response" in 969 [Nn] | [Nn][Oo]) 970 return 0 971 ;; 972 esac 973 fi 974 975 ipkg_install $wanted 976 fi 977 978 return 0 979} 980 981ipkg_upgrade_pkg() { 982 local pkg="$1" 983 local avail_ver="`ipkg_info $pkg Version | ipkg_extract_value | head -n 1`" 984 985 is_installed= 986 for dest_name in `ipkg_dest_names`; do 987 local dest="`ipkg_dest_byname $dest_name`" 988 local sd=$dest/$IPKG_DIR_PREFIX 989 local inst_ver="`ipkg_status_sd $sd $pkg Version | ipkg_extract_value`" 990 if [ -n "$inst_ver" ]; then 991 is_installed=t 992 993 if [ -z "$avail_ver" ]; then 994 echo "Assuming locally installed package $pkg ($inst_ver) is up to date" 995 return 0 996 fi 997 998 if [ "$avail_ver" = "$inst_ver" ]; then 999 echo "Package $pkg ($inst_ver) installed in $dest_name is up to date" 1000 elif ipkg_is_upgrade "$avail_ver" "$inst_ver"; then 1001 echo "Upgrading $pkg ($dest_name) from $inst_ver to $avail_ver" 1002 ipkg_get_install_dest $dest $pkg 1003 else 1004 echo "Not downgrading package $pkg from $inst_ver to $avail_ver" 1005 fi 1006 fi 1007 done 1008 1009 if [ -z "$is_installed" ]; then 1010 echo "Package $pkg does not appear to be installed" 1011 return 0 1012 fi 1013 1014} 1015 1016ipkg_upgrade() { 1017 if [ $# -lt 1 ]; then 1018 local pkgs="`ipkg_status_matching 'Status:.*[[:space:]]installed'`" 1019 else 1020 pkgs="$*" 1021 fi 1022 1023 for pkg in $pkgs; do 1024 ipkg_upgrade_pkg $pkg 1025 done 1026} 1027 1028ipkg_remove_pkg_dest() { 1029 local dest="$1" 1030 local pkg="$2" 1031 local sd=$dest/$IPKG_DIR_PREFIX 1032 local info_dir=$sd/info 1033 1034 if ! ipkg_status_installed_sd $sd $pkg; then 1035 echo "ipkg_remove: Package $pkg does not appear to be installed in $dest" 1036 if ipkg_status_mentioned_sd $sd $pkg; then 1037 echo "Purging mention of $pkg from the ipkg database" 1038 ipkg_status_remove_sd $sd $pkg 1039 fi 1040 return 1 1041 fi 1042 1043 echo "ipkg_remove: Removing $pkg... " 1044 1045 local files="`cat $info_dir/$pkg.list`" 1046 1047 export PKG_ROOT=$dest 1048 if [ -x "$info_dir/$pkg.prerm" ]; then 1049 $info_dir/$pkg.prerm remove 1050 fi 1051 1052 local conffiles="`ipkg_status_sd $sd $pkg Conffiles | ipkg_extract_value`" 1053 1054 local dirs_to_remove= 1055 for file in $files; do 1056 if [ -d "$dest/$file" ]; then 1057 dirs_to_remove="$dirs_to_remove $dest/$file" 1058 else 1059 if echo " $conffiles " | grep -q " $file "; then 1060 if echo " $conffiles " | grep -q " $file "`md5sum $dest/$file | sed 's/ .*//'`; then 1061 rm -f $dest/$file 1062 fi 1063 else 1064 rm -f $dest/$file 1065 fi 1066 fi 1067 done 1068 1069 local removed_a_dir=t 1070 while [ -n "$removed_a_dir" ]; do 1071 removed_a_dir= 1072 local new_dirs_to_remove= 1073 for dir in $dirs_to_remove; do 1074 if rmdir $dir >/dev/null 2>&1; then 1075 removed_a_dir=t 1076 else 1077 new_dirs_to_remove="$new_dirs_to_remove $dir" 1078 fi 1079 done 1080 dirs_to_remove="$new_dirs_to_remove" 1081 done 1082 1083 if [ -n "$dirs_to_remove" ]; then 1084 echo "ipkg_remove: Warning: Not removing the following directories since they are not empty:" >&2 1085 echo "$dirs_to_remove" | sed -e 's/\/[/]\+/\//g' >&2 1086 fi 1087 1088 if [ -x "$info_dir/$pkg.postrm" ]; then 1089 $info_dir/$pkg.postrm remove 1090 fi 1091 1092 ipkg_status_remove_sd $sd $pkg 1093 set +o noglob 1094 rm -f $info_dir/$pkg.* 1095 set -o noglob 1096 1097 echo "Done." 1098} 1099 1100ipkg_remove_pkg() { 1101 local pkg="$1" 1102 for dest in `ipkg_dests_all`; do 1103 local sd=$dest/$IPKG_DIR_PREFIX 1104 if ipkg_status_mentioned_sd $sd $pkg; then 1105 ipkg_remove_pkg_dest $dest $pkg 1106 fi 1107 done 1108} 1109 1110ipkg_remove() { 1111 while [ $# -gt 0 ]; do 1112 local pkg="$1" 1113 shift 1114 if [ -n "$DEST_NAME" ]; then 1115 ipkg_remove_pkg_dest $IPKG_ROOT $pkg 1116 else 1117 ipkg_remove_pkg $pkg 1118 fi 1119 done 1120} 1121 1122########### 1123# ipkg main 1124########### 1125 1126# Parse options 1127while [ $# -gt 0 ]; do 1128 arg="$1" 1129 case $arg in 1130 -d | -dest) 1131 [ $# -gt 1 ] || ipkg_usage "option $arg requires an argument" 1132 DEST_NAME="$2" 1133 shift 1134 ;; 1135 -o | -offline) 1136 [ $# -gt 1 ] || ipkg_usage "option $arg requires an argument" 1137 IPKG_OFFLINE_ROOT="$2" 1138 shift 1139 ;; 1140 -force-depends) 1141 FORCE_DEPENDS=t 1142 ;; 1143 -force-defaults) 1144 FORCE_DEFAULTS=t 1145 ;; 1146 -*) 1147 ipkg_usage "unknown option $arg" 1148 ;; 1149 *) 1150 break 1151 ;; 1152 esac 1153 shift 1154done 1155 1156[ $# -lt 1 ] && ipkg_usage "ipkg must have one sub-command argument" 1157cmd="$1" 1158shift 1159 1160ipkg_load_configuration 1161mkdir -p /tmp/ipkg 1162 1163case "$cmd" in 1164update|upgrade|list|info|status|install_pending) 1165 ;; 1166install|depends|remove|files|search) 1167 [ $# -lt 1 ] && ipkg_usage "ERROR: the \`\`$cmd'' command requires an argument" 1168 ;; 1169*) 1170 echo "ERROR: unknown sub-command \`$cmd'" 1171 ipkg_usage 1172 ;; 1173esac 1174 1175# Only install pending if we have an interactive sub-command 1176case "$cmd" in 1177upgrade|install) 1178 ipkg_install_pending 1179 ipkg_install_wanted 1180 ;; 1181esac 1182 1183ipkg_$cmd $* 1184for a in `ls $IPKG_TMP`; do 1185 rm -rf $IPKG_TMP/$a 1186done 1187