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