#!/bin/sh # ipkg - the itsy package management system # # Copyright (C) 2001 Carl D. Worth # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. set -e # By default do not do globbing. Any command wanting globbing should # explicitly enable it first and disable it afterwards. set -o noglob ipkg_is_upgrade () { local A B a b A=$(echo $1 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g"). B=$(echo $2 | sed -r "s/([0-9]+)[^[:alnum:]]*/ \1 /g"). while [ \! -z "$A" ] && [ \! -z "$B" ]; do { set $A; a=$1; shift; A=$* set $B; b=$1; shift; B=$* [ "$a" -lt "$b" ] 2>&- && return 1 { [ "$a" -gt "$b" ] 2>&- || [ "$a" ">" "$b" ]; } && return }; done return 1 } which md5sum 2>&1 >/dev/null || alias md5sum=md5 ipkg_srcs() { local srcre="$1" sed -ne "s/^src[[:space:]]\+$srcre[[:space:]]\+//p" < $IPKG_CONF } ipkg_src_names() { sed -ne "s/^src[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF } ipkg_src_byname() { local src="$1" ipkg_srcs $src | head -n 1 } ipkg_dests() { local destre="`echo $1 | ipkg_protect_slashes`" sed -ne "/^dest[[:space:]]\+$destre/{ s/^dest[[:space:]]\+[^[:space:]]\+[[:space:]]\+// s/^/`echo $IPKG_OFFLINE_ROOT | ipkg_protect_slashes`/ p }" < $IPKG_CONF } ipkg_dest_names() { sed -ne "s/^dest[[:space:]]\+\([^[:space:]]\+\).*/\1/p" < $IPKG_CONF } ipkg_dests_all() { ipkg_dests '.*' } ipkg_state_dirs() { ipkg_dests_all | sed "s|\$|/$IPKG_DIR_PREFIX|" } ipkg_dest_default() { ipkg_dests_all | head -n 1 } ipkg_dest_default_name() { ipkg_dest_names | head -n 1 } ipkg_dest_byname() { local dest="$1" ipkg_dests $dest | head -n 1 } ipkg_option() { local option="$1" sed -ne "s/^option[[:space:]]\+$option[[:space:]]\+//p" < $IPKG_CONF } ipkg_load_configuration() { if [ -z "$IPKG_CONF_DIR" ]; then IPKG_CONF_DIR=/etc fi IPKG_CONF="$IPKG_CONF_DIR/ipkg.conf" if [ -z "$IPKG_OFFLINE_ROOT" ]; then IPKG_OFFLINE_ROOT="`ipkg_option offline_root`" fi # Export IPKG_OFFLINE_ROOT for use by update-alternatives export IPKG_OFFLINE_ROOT if [ -n "$DEST_NAME" ]; then IPKG_ROOT="`ipkg_dest_byname $DEST_NAME`" if [ -z "$IPKG_ROOT" ]; then if [ -d "$IPKG_OFFLINE_ROOT$DEST_NAME" ]; then IPKG_ROOT="$IPKG_OFFLINE_ROOT$DEST_NAME"; else echo "ipkg: invalid destination specification: $DEST_NAME Valid destinations are directories or one of the dest names from $IPKG_CONF:" >&2 ipkg_dest_names >&2 return 1 fi fi else IPKG_ROOT="`ipkg_dest_default`" fi # Global ipkg state directories IPKG_DIR_PREFIX=usr/lib/opkg IPKG_LISTS_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/lists IPKG_PENDING_DIR=$IPKG_OFFLINE_ROOT/$IPKG_DIR_PREFIX/pending if [ -z "$IPKG_TMP" ]; then IPKG_TMP=$IPKG_ROOT/tmp/ipkg fi [ -e "$IPKG_TMP" ] || mkdir -p $IPKG_TMP # Destination specific ipkg meta-data directory IPKG_STATE_DIR=$IPKG_ROOT/$IPKG_DIR_PREFIX # Proxy Support IPKG_PROXY_USERNAME="`ipkg_option proxy_username`" IPKG_PROXY_PASSWORD="`ipkg_option proxy_password`" IPKG_HTTP_PROXY="`ipkg_option http_proxy`" IPKG_FTP_PROXY="`ipkg_option ftp_proxy`" IPKG_NO_PROXY="`ipkg_option no_proxy`" if [ -n "$IPKG_HTTP_PROXY" ]; then export http_proxy="$IPKG_HTTP_PROXY" fi if [ -n "$IPKG_FTP_PROXY" ]; then export ftp_proxy="$IPKG_FTP_PROXY" fi if [ -n "$IPKG_NO_PROXY" ]; then export no_proxy="$IPKG_NO_PROXY" fi IPKG_STATUS_FIELDS='\(Package\|Status\|Essential\|Version\|Conffiles\|Root\|Architecture\)' } ipkg_usage() { [ $# -gt 0 ] && echo "ipkg: $*" echo " usage: ipkg [options...] sub-command [arguments...] where sub-command is one of: Package Manipulation: update Update list of available packages upgrade Upgrade all installed packages to latest version install Download and install (and dependencies) install Install package install Install package remove Remove package Informational Commands: list List available packages and descriptions files List all files belonging to search Search for a packaging providing info [pkg []] Display all/some info fields for or all status [pkg []] Display all/some status fields for or all depends Print uninstalled package dependencies for Options: -d Use as the the root directory for -dest package installation, removal, upgrading. should be a defined dest name from the configuration file, (but can also be a directory name in a pinch). -o Use as the root for offline installation. -offline Force Options (use when ipkg is too smart for its own good): -force-depends Make dependency checks warnings instead of errors -force-defaults Use default options for questions asked by ipkg. (no prompts). Note that this will not prevent package installation scripts from prompting. " >&2 exit 1 } ipkg_dir_part() { local dir="`echo $1 | sed -ne 's/\(.*\/\).*/\1/p'`" if [ -z "$dir" ]; then dir="./" fi echo $dir } ipkg_file_part() { echo $1 | sed 's/.*\///' } ipkg_protect_slashes() { sed -e 's/\//\\\//g' } ipkg_download() { local src="$1" local dest="$2" local src_file="`ipkg_file_part $src`" local dest_dir="`ipkg_dir_part $dest`" if [ -z "$dest_dir" ]; then dest_dir="$IPKG_TMP" fi local dest_file="`ipkg_file_part $dest`" if [ -z "$dest_file" ]; then dest_file="$src_file" fi # Proxy support local proxyuser="" local proxypassword="" local proxyoption="" if [ -n "$IPKG_PROXY_USERNAME" ]; then proxyuser="--proxy-user=\"$IPKG_PROXY_USERNAME\"" proxypassword="--proxy-passwd=\"$IPKG_PROXY_PASSWORD\"" fi if [ -n "$IPKG_PROXY_HTTP" -o -n "$IPKG_PROXY_FTP" ]; then proxyoption="--proxy=on" fi rm -f $IPKG_TMP/$src_file case "$src" in http://* | ftp://*) if ! wget --passive-ftp $proxyoption $proxyuser $proxypassword -P $IPKG_TMP $src; then echo "ipkg_download: ERROR: Failed to retrieve $src, returning $err" >&2 return 1 fi mv $IPKG_TMP/$src_file $dest_dir/$dest_file 2>/dev/null ;; file:/* ) ln -s `echo $src | sed 's/^file://'` $dest_dir/$dest_file 2>/dev/null ;; *) echo "DEBUG: $src" ;; esac return 0 } ipkg_update() { if [ ! -e "$IPKG_LISTS_DIR" ]; then mkdir -p $IPKG_LISTS_DIR fi local err= for src_name in `ipkg_src_names`; do local src="`ipkg_src_byname $src_name`" if ! ipkg_download $src/Packages $IPKG_LISTS_DIR/$src_name; then echo "ipkg_update: Error downloading $src/Packages to $IPKG_LISTS_DIR/$src_name" >&2 err=t else echo "Updated list of available packages in $IPKG_LISTS_DIR/$src_name" fi done [ -n "$err" ] && return 1 return 0 } ipkg_list() { for src in `ipkg_src_names`; do if ipkg_require_list $src; then # black magic... sed -ne " /^Package:/{ s/^Package:[[:space:]]*\<\([a-z0-9.+-]*$1[a-z0-9.+-]*\).*/\1/ h } /^Description:/{ s/^Description:[[:space:]]*\(.*\)/\1/ H g s/\\ / - / p } " $IPKG_LISTS_DIR/$src fi done } ipkg_extract_paragraph() { local pkg="$1" sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/p" } ipkg_extract_field() { local field="$1" # blacker magic... sed -ne " : TOP /^$field:/{ p n b FIELD } d : FIELD /^$/b TOP /^[^[:space:]]/b TOP p n b FIELD " } ipkg_extract_value() { sed -e "s/^[^:]*:[[:space:]]*//" } ipkg_require_list() { [ $# -lt 1 ] && return 1 local src="$1" if [ ! -f "$IPKG_LISTS_DIR/$src" ]; then echo "ERROR: File not found: $IPKG_LISTS_DIR/$src" >&2 echo " You probably want to run \`ipkg update'" >&2 return 1 fi return 0 } ipkg_info() { for src in `ipkg_src_names`; do if ipkg_require_list $src; then case $# in 0) cat $IPKG_LISTS_DIR/$src ;; 1) ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src ;; *) ipkg_extract_paragraph $1 < $IPKG_LISTS_DIR/$src | ipkg_extract_field $2 ;; esac fi done } ipkg_status_sd() { [ $# -lt 1 ] && return 0 sd="$1" shift if [ -f $sd/status ]; then case $# in 0) cat $sd/status ;; 1) ipkg_extract_paragraph $1 < $sd/status ;; *) ipkg_extract_paragraph $1 < $sd/status | ipkg_extract_field $2 ;; esac fi return 0 } ipkg_status_all() { for sd in `ipkg_state_dirs`; do ipkg_status_sd $sd $* done } ipkg_status() { if [ -n "$DEST_NAME" ]; then ipkg_status_sd $IPKG_STATE_DIR $* else ipkg_status_all $* fi } ipkg_status_matching_sd() { local sd="$1" local re="$2" if [ -f $sd/status ]; then sed -ne " : TOP /^Package:/{ s/^Package:[[:space:]]*// s/[[:space:]]*$// h } /$re/{ g p b NEXT } d : NEXT /^$/b TOP n b NEXT " < $sd/status fi return 0 } ipkg_status_matching_all() { for sd in `ipkg_state_dirs`; do ipkg_status_matching_sd $sd $* done } ipkg_status_matching() { if [ -n "$DEST_NAME" ]; then ipkg_status_matching_sd $IPKG_STATE_DIR $* else ipkg_status_matching_all $* fi } ipkg_status_installed_sd() { local sd="$1" local pkg="$2" ipkg_status_sd $sd $pkg Status | grep -q "Status: install ok installed" } ipkg_status_installed_all() { local ret=1 for sd in `ipkg_state_dirs`; do if `ipkg_status_installed_sd $sd $*`; then ret=0 fi done return $ret } ipkg_status_mentioned_sd() { local sd="$1" local pkg="$2" [ -n "`ipkg_status_sd $sd $pkg Status`" ] } ipkg_files() { local pkg="$1" if [ -n "$DEST_NAME" ]; then dests=$IPKG_ROOT else dests="`ipkg_dests_all`" fi for dest in $dests; do if [ -f $dest/$IPKG_DIR_PREFIX/info/$pkg.list ]; then dest_sed="`echo $dest | ipkg_protect_slashes`" sed -e "s/^/$dest_sed/" < $dest/$IPKG_DIR_PREFIX/info/$pkg.list fi done } ipkg_search() { local pattern="$1" for dest_name in `ipkg_dest_names`; do dest="`ipkg_dest_byname $dest_name`" dest_sed="`echo $dest | ipkg_protect_slashes`" set +o noglob local list_files="`ls -1 $dest/$IPKG_DIR_PREFIX/info/*.list 2>/dev/null`" set -o noglob for file in $list_files; do if sed "s/^/$dest_sed/" $file | grep -q $pattern; then local pkg="`echo $file | sed "s/^.*\/\(.*\)\.list/\1/"`" [ "$dest_name" != `ipkg_dest_default_name` ] && pkg="$pkg ($dest_name)" sed "s/^/$dest_sed/" $file | grep $pattern | sed "s/^/$pkg: /" fi done done } ipkg_status_remove_sd() { local sd="$1" local pkg="$2" if [ ! -f $sd/status ]; then mkdir -p $sd touch $sd/status fi sed -ne "/Package:[[:space:]]*$pkg[[:space:]]*\$/,/^\$/!p" < $sd/status > $sd/status.new mv $sd/status.new $sd/status } ipkg_status_remove_all() { for sd in `ipkg_state_dirs`; do ipkg_status_remove_sd $sd $* done } ipkg_status_remove() { if [ -n "$DEST_NAME" ]; then ipkg_status_remove_sd $IPKG_STATE_DIR $* else ipkg_status_remove_all $* fi } ipkg_status_update_sd() { local sd="$1" local pkg="$2" ipkg_status_remove_sd $sd $pkg ipkg_extract_field "$IPKG_STATUS_FIELDS" >> $sd/status echo "" >> $sd/status } ipkg_status_update() { ipkg_status_update_sd $IPKG_STATE_DIR $* } ipkg_unsatisfied_dependences() { local pkg=$1 local deps="`ipkg_get_depends $pkg`" local remaining_deps= for dep in $deps; do local installed="`ipkg_get_installed $dep`" if [ "$installed" != "installed" ] ; then remaining_deps="$remaining_deps $dep" fi done ## echo "ipkg_unsatisfied_dependences pkg=$pkg $remaining_deps" > /dev/console echo $remaining_deps } ipkg_safe_pkg_name() { local pkg=$1 local spkg="`echo pkg_$pkg | sed -e y/-+./___/`" echo $spkg } ipkg_set_depends() { local pkg=$1; shift local new_deps="$*" pkg="`ipkg_safe_pkg_name $pkg`" ## setvar ${pkg}_depends "$new_deps" echo $new_deps > $IPKG_TMP/${pkg}.depends } ipkg_get_depends() { local pkg=$1 pkg="`ipkg_safe_pkg_name $pkg`" cat $IPKG_TMP/${pkg}.depends ## eval "echo \$${pkg}_depends" } ipkg_set_installed() { local pkg=$1 pkg="`ipkg_safe_pkg_name $pkg`" echo installed > $IPKG_TMP/${pkg}.installed ## setvar ${pkg}_installed "installed" } ipkg_set_uninstalled() { local pkg=$1 pkg="`ipkg_safe_pkg_name $pkg`" ### echo ipkg_set_uninstalled $pkg > /dev/console echo uninstalled > $IPKG_TMP/${pkg}.installed ## setvar ${pkg}_installed "uninstalled" } ipkg_get_installed() { local pkg=$1 pkg="`ipkg_safe_pkg_name $pkg`" if [ -f $IPKG_TMP/${pkg}.installed ]; then cat $IPKG_TMP/${pkg}.installed fi ## eval "echo \$${pkg}_installed" } ipkg_depends() { local new_pkgs="$*" local all_deps= local installed_pkgs="`ipkg_status_matching_all 'Status:.*[[:space:]]installed'`" for pkg in $installed_pkgs; do ipkg_set_installed $pkg done while [ -n "$new_pkgs" ]; do all_deps="$all_deps $new_pkgs" local new_deps= for pkg in $new_pkgs; do if echo $pkg | grep -q '[^A-Za-z0-9.+-]'; then echo "ipkg_depends: ERROR: Package name $pkg contains illegal characters (should be [A-Za-z0-9.+-])" >&2 return 1 fi # TODO: Fix this. For now I am ignoring versions and alternations in dependencies. new_deps="$new_deps "`ipkg_info $pkg '\(Pre-\)\?Depends' | ipkg_extract_value | sed -e 's/([^)]*)//g s/\(|[[:space:]]*[a-z0-9.+-]\+[[:space:]]*\)\+//g s/,/ /g s/ \+/ /g'` ipkg_set_depends $pkg $new_deps done new_deps=`echo $new_deps | sed -e 's/[[:space:]]\+/\n/g' | sort | uniq` local maybe_new_pkgs= for pkg in $new_deps; do if ! echo $installed_pkgs | grep -q "\<$pkg\>"; then maybe_new_pkgs="$maybe_new_pkgs $pkg" fi done new_pkgs= for pkg in $maybe_new_pkgs; do if ! echo $all_deps | grep -q "\<$pkg\>"; then if [ -z "`ipkg_info $pkg`" ]; then echo "ipkg_depends: Warning: $pkg mentioned in dependency but no package found in $IPKG_LISTS_DIR" >&2 ipkg_set_installed $pkg else new_pkgs="$new_pkgs $pkg" ipkg_set_uninstalled $pkg fi else ipkg_set_uninstalled $pkg fi done done echo $all_deps } ipkg_get_install_dest() { local dest="$1" shift local sd=$dest/$IPKG_DIR_PREFIX local info_dir=$sd/info local requested_pkgs="$*" local pkgs="`ipkg_depends $*`" mkdir -p $info_dir for pkg in $pkgs; do if ! ipkg_status_mentioned_sd $sd $pkg; then echo "Package: $pkg Status: install ok not-installed" | ipkg_status_update_sd $sd $pkg fi done ## mark the packages that we were directly requested to install as uninstalled for pkg in $requested_pkgs; do ipkg_set_uninstalled $pkg; done local new_pkgs= local pkgs_installed=0 while [ -n "pkgs" ]; do curcheck=0 ## echo "pkgs to install: {$pkgs}" > /dev/console for pkg in $pkgs; do curcheck="`expr $curcheck + 1`" local is_installed="`ipkg_get_installed $pkg`" if [ "$is_installed" = "installed" ]; then echo "$pkg is installed" continue fi local remaining_deps="`ipkg_unsatisfied_dependences $pkg`" if [ -n "$remaining_deps" ]; then new_pkgs="$new_pkgs $pkg" ### echo "Dependences not satisfied for $pkg: $remaining_deps" if [ $curcheck -ne `echo $pkgs|wc -w` ]; then continue fi fi local filename= for src in `ipkg_src_names`; do if ipkg_require_list $src; then filename="`ipkg_extract_paragraph $pkg < $IPKG_LISTS_DIR/$src | ipkg_extract_field Filename | ipkg_extract_value`" [ -n "$filename" ] && break fi done if [ -z "$filename" ]; then echo "ipkg_get_install: ERROR: Cannot find package $pkg in $IPKG_LISTS_DIR" >&2 echo "ipkg_get_install: Check the spelling and maybe run \`ipkg update'." >&2 ipkg_status_remove_sd $sd $pkg return 1; fi local tmp_pkg_file="$IPKG_TMP/"`ipkg_file_part $filename` if ! ipkg_download `ipkg_src_byname $src`/$filename $tmp_pkg_file; then echo "ipkg_get_install: Perhaps you need to run \`ipkg update'?" return 1 fi if ! ipkg_install_file_dest $dest $tmp_pkg_file; then echo "ipkg_get_install: ERROR: Failed to install $tmp_pkg_file" >&2 echo "ipkg_get_install: I'll leave it there for you to try a manual installation" >&2 return 1 fi ipkg_set_installed $pkg pkgs_installed="`expr $pkgs_installed + 1`" rm $tmp_pkg_file done ### echo "Installed $pkgs_installed package(s) this round" if [ $pkgs_installed -eq 0 ]; then if [ -z "$new_pkgs" ]; then break fi fi pkgs_installed=0 pkgs="$new_pkgs" new_pkgs= curcheck=0 done } ipkg_get_install() { ipkg_get_install_dest $IPKG_ROOT $* } ipkg_install_file_dest() { local dest="$1" local filename="$2" local sd=$dest/$IPKG_DIR_PREFIX local info_dir=$sd/info if [ ! -f "$filename" ]; then echo "ipkg_install_file: ERROR: File $filename not found" >&2 return 1 fi local pkg="`ipkg_file_part $filename | sed 's/\([a-z0-9.+-]\+\)_.*/\1/'`" local ext="`echo $filename | sed 's/.*\.//'`" local pkg_extract_stdout if [ "$ext" = "ipk" ]; then pkg_extract_stdout="tar -xzOf" elif [ "$ext" = "deb" ]; then pkg_extract_stdout="ar p" else echo "ipkg_install_file: ERROR: File $filename has unknown extension $ext (not .ipk or .deb)" >&2 return 1 fi # Check dependencies local depends="`ipkg_depends $pkg | sed -e "s/\<$pkg\>//"`" # Don't worry about deps that are scheduled for installation local missing_deps= for dep in $depends; do if ! ipkg_status_all $dep | grep -q 'Status:[[:space:]]install'; then missing_deps="$missing_deps $dep" fi done if [ ! -z "$missing_deps" ]; then if [ -n "$FORCE_DEPENDS" ]; then echo "ipkg_install_file: Warning: $pkg depends on the following uninstalled programs: $missing_deps" >&2 else echo "ipkg_install_file: ERROR: $pkg depends on the following uninstalled programs: $missing_deps" >&2 echo "ipkg_install_file: You may want to use \`ipkg install' to install these." >&2 return 1 fi fi mkdir -p $IPKG_TMP/$pkg/control mkdir -p $IPKG_TMP/$pkg/data mkdir -p $info_dir if ! $pkg_extract_stdout $filename ./control.tar.gz | (cd $IPKG_TMP/$pkg/control; zcat | tar -xf - ) ; then echo "ipkg_install_file: ERROR unpacking control.tar.gz from $filename" >&2 return 1 fi if [ -n "$IPKG_OFFLINE_ROOT" ]; then if grep -q '^InstallsOffline:[[:space:]]*no' $IPKG_TMP/$pkg/control/control; then echo "*** Warning: Package $pkg may not be installed in offline mode" >&2 echo "*** Warning: Scheduling $filename for pending installation (installing into $IPKG_PENDING_DIR)" >&2 echo "Package: $pkg Status: install ok pending" | ipkg_status_update_sd $sd $pkg mkdir -p $IPKG_PENDING_DIR cp -f $filename $IPKG_PENDING_DIR rm -r $IPKG_TMP/$pkg/control rm -r $IPKG_TMP/$pkg/data rmdir $IPKG_TMP/$pkg return 0 fi fi printf "Unpacking $pkg..." set +o noglob for file in $IPKG_TMP/$pkg/control/*; do local base_file="`ipkg_file_part $file`" mv $file $info_dir/$pkg.$base_file done set -o noglob rm -r $IPKG_TMP/$pkg/control if ! $pkg_extract_stdout $filename ./data.tar.gz | (cd $IPKG_TMP/$pkg/data; zcat | tar -xf - ) ; then echo "ipkg_install_file: ERROR unpacking data.tar.gz from $filename" >&2 return 1 fi echo "Done." printf "Configuring $pkg..." export PKG_ROOT=$dest if [ -x "$info_dir/$pkg.preinst" ]; then if ! $info_dir/$pkg.preinst install; then echo "$info_dir/$pkg.preinst failed. Aborting installation of $pkg" rm -rf $IPKG_TMP/$pkg/data rmdir $IPKG_TMP/$pkg return 1 fi fi local old_conffiles="`ipkg_status_sd $sd $pkg Conffiles | ipkg_extract_value`" local new_conffiles= if [ -f "$info_dir/$pkg.conffiles" ]; then for conffile in `cat $info_dir/$pkg.conffiles`; do if [ -f "$dest/$conffile" ] && ! echo " $old_conffiles " | grep -q " $conffile "`md5sum $dest/$conffile | sed 's/ .*//'`; then local use_maintainers_conffile= if [ -z "$FORCE_DEFAULTS" ]; then while true; do printf "Configuration file \`$conffile' ==> File on system created by you or by a script. ==> File also in package provided by package maintainer. What would you like to do about it ? Your options are: Y or I : install the package maintainer's version N or O : keep your currently-installed version D : show the differences between the versions (if diff is installed) The default action is to keep your current version. *** `ipkg_file_part $conffile` (Y/I/N/O/D) [default=N] ? " read response case "$response" in [YyIi] | [Yy][Ee][Ss]) use_maintainers_conffile=t break ;; [Dd]) echo " diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile" diff -u $dest/$conffile $IPKG_TMP/$pkg/data/$conffile || true echo "[Press ENTER to continue]" read junk ;; *) break ;; esac done fi if [ -n "$use_maintainers_conffile" ]; then local md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`" new_conffiles="$new_conffiles $conffile $md5sum" else new_conffiles="$new_conffiles $conffile " rm $IPKG_TMP/$pkg/data/$conffile fi else md5sum="`md5sum $IPKG_TMP/$pkg/data/$conffile | sed 's/ .*//'`" new_conffiles="$new_conffiles $conffile $md5sum" fi done fi local owd="`pwd`" (cd $IPKG_TMP/$pkg/data/; tar cf - . | (cd $owd; cd $dest; tar xf -)) rm -rf $IPKG_TMP/$pkg/data rmdir $IPKG_TMP/$pkg rm -f $info_dir/$pkg.list $pkg_extract_stdout $filename ./data.tar.gz | zcat | tar tf - | sed -e '/\/$/d; s/^\.//' > $info_dir/$pkg.list if [ -x "$info_dir/$pkg.postinst" ]; then $info_dir/$pkg.postinst configure fi if [ -n "$new_conffiles" ]; then new_conffiles='Conffiles: '`echo $new_conffiles | ipkg_protect_slashes` fi local sed_safe_offline_root="`echo ${IPKG_OFFLINE_ROOT} | ipkg_protect_slashes`" local sed_safe_root="`echo $dest | sed -e "s/^${sed_safe_offline_root}//" | ipkg_protect_slashes`" sed -e "s/\(Package:.*\)/\1\\ Status: install ok installed\\ Root: ${sed_safe_root}\\ ${new_conffiles}/" $info_dir/$pkg.control | ipkg_status_update_sd $sd $pkg rm -f $info_dir/$pkg.control rm -f $info_dir/$pk
#
# Copyright (C) 2006-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

override TARGET_BUILD=
include $(INCLUDE_DIR)/prereq.mk
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/host.mk
include $(INCLUDE_DIR)/version.mk
include $(INCLUDE_DIR)/image-commands.mk

ifndef IB
  ifdef CONFIG_TARGET_PER_DEVICE_ROOTFS
    TARGET_PER_DEVICE_ROOTFS := 1
  endif
endif

include $(INCLUDE_DIR)/image-legacy.mk

ifdef TARGET_PER_DEVICE_ROOTFS
  include $(INCLUDE_DIR)/rootfs.mk
endif

override MAKE:=$(_SINGLE)$(SUBMAKE)
override NO_TRACE_MAKE:=$(_SINGLE)$(NO_TRACE_MAKE)

target_params = $(subst +,$(space),$*)
param_get = $(patsubst $(1)=%,%,$(filter $(1)=%,$(2)))
param_get_default = $(firstword $(call param_get,$(1),$(2)) $(3))
param_mangle = $(subst $(space),_,$(strip $(1)))
param_unmangle = $(subst _,$(space),$(1))

mkfs_packages_id = $(shell echo $(sort $(1)) | md5sum | head -c 8)
mkfs_target_dir = $(if $(call param_get,pkg,$(1)),$(KDIR)/target-dir-$(call param_get,pkg,$(1)),$(TARGET_DIR))

KDIR=$(KERNEL_BUILD_DIR)
KDIR_TMP=$(KDIR)/tmp
DTS_DIR:=$(LINUX_DIR)/arch/$(LINUX_KARCH)/boot/dts

EXTRA_NAME_SANITIZED=$(call sanitize,$(EXTRA_IMAGE_NAME))

IMG_PREFIX:=$(VERSION_DIST_SANITIZED)-$(if $(CONFIG_VERSION_FILENAMES),$(VERSION_NUMBER)-)$(if $(EXTRA_NAME_SANITIZED),$(EXTRA_NAME_SANITIZED)-)$(BOARD)$(if $(SUBTARGET),-$(SUBTARGET))

MKFS_DEVTABLE_OPT := -D $(INCLUDE_DIR)/device_table.txt

ifneq ($(CONFIG_BIG_ENDIAN),)
  JFFS2OPTS     :=  --big-endian --squash-uids -v
else
  JFFS2OPTS     :=  --little-endian --squash-uids -v
endif

ifeq ($(CONFIG_JFFS2_RTIME),y)
  JFFS2OPTS += -X rtime
endif
ifeq ($(CONFIG_JFFS2_ZLIB),y)
  JFFS2OPTS += -X zlib
endif
ifeq ($(CONFIG_JFFS2_LZMA),y)
  JFFS2OPTS += -X lzma --compression-mode=size
endif
ifneq ($(CONFIG_JFFS2_RTIME),y)
  JFFS2OPTS += -x rtime
endif
ifneq ($(CONFIG_JFFS2_ZLIB),y)
  JFFS2OPTS += -x zlib
endif
ifneq ($(CONFIG_JFFS2_LZMA),y)
  JFFS2OPTS += -x lzma
endif

JFFS2OPTS += $(MKFS_DEVTABLE_OPT)

SQUASHFS_BLOCKSIZE := $(CONFIG_TARGET_SQUASHFS_BLOCK_SIZE)k
SQUASHFSOPT := -b $(SQUASHFS_BLOCKSIZE)
SQUASHFSOPT += -p '/dev d 755 0 0' -p '/dev/console c 600 0 0 5 1'
SQUASHFSCOMP := gzip
LZMA_XZ_OPTIONS := -Xpreset 9 -Xe -Xlc 0 -Xlp 2 -Xpb 2
ifeq ($(CONFIG_SQUASHFS_XZ),y)
  ifneq ($(filter arm x86 powerpc sparc,$(LINUX_KARCH)),)
    BCJ_FILTER:=-Xbcj $(LINUX_KARCH)
  endif
  SQUASHFSCOMP := xz $(LZMA_XZ_OPTIONS) $(BCJ_FILTER)
endif

JFFS2_BLOCKSIZE ?= 64k 128k

fs-types-$(CONFIG_TARGET_ROOTFS_SQUASHFS) += squashfs
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addprefix jffs2-,$(JFFS2_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2_NAND) += $(addprefix jffs2-nand-,$(NAND_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_EXT4FS) += ext4
fs-types-$(CONFIG_TARGET_ROOTFS_ISO) += iso
fs-types-$(CONFIG_TARGET_ROOTFS_UBIFS) += ubifs
fs-subtypes-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addsuffix -raw,$(addprefix jffs2-,$(JFFS2_BLOCKSIZE)))

TARGET_FILESYSTEMS := $(fs-types-y)

FS_64K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-64k
FS_128K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-128k
FS_256K := $(filter-out jffs2-%,$(TARGET_FILESYSTEMS)) jffs2-256k

define add_jffs2_mark
	echo -ne '\xde\xad\xc0\xde' >> $(1)
endef

PROFILE_SANITIZED := $(call sanitize,$(PROFILE))

define split_args
$(foreach data, \
	$(subst |,$(space),\
		$(subst $(space),^,$(1))), \
	$(call $(2),$(strip $(subst ^,$(space),$(data)))))
endef

define build_cmd
$(if $(Build/$(word 1,$(1))),,$(error Missing Build/$(word 1,$(1))))
$(call Build/$(word 1,$(1)),$(wordlist 2,$(words $(1)),$(1)))

endef

define concat_cmd
$(call split_args,$(1),build_cmd)
endef

# pad to 4k, 8k, 16k, 64k, 128k, 256k and add jffs2 end-of-filesystem mark
define prepare_generic_squashfs
	$(STAGING_DIR_HOST)/bin/padjffs2 $(1) 4 8 16 64 128 256
endef

define Image/BuildKernel/Initramfs
	$(call Image/Build/Initramfs)
endef

define Image/BuildKernel/MkuImage
	mkimage -A $(ARCH) -O linux -T kernel -C $(1) -a $(2) -e $(3) \
		-n '$(call toupper,$(ARCH)) LEDE Linux-$(LINUX_VERSION)' -d $(4) $(5)
endef

define Image/BuildKernel/MkFIT
	$(TOPDIR)/scripts/mkits.sh \
		-D $(1) -o $(KDIR)/fit-$(1).its -k $(2) $(if $(3),-d $(3)) -C $(4) -a $(5) -e $(6) \
		-A $(ARCH) -v $(LINUX_VERSION)
	PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $(KDIR)/fit-$(1).its $(KDIR)/fit-$(1)$(7).itb
endef

# $(1) source dts file
# $(2) target dtb file
# $(3) extra CPP flags
# $(4) extra DTC flags
define Image/BuildDTB
	$(TARGET_CROSS)cpp -nostdinc -x assembler-with-cpp \
		-I$(DTS_DIR) \
		-I$(DTS_DIR)/include \
		-undef -D__DTS__ $(3) \
		-o $(2).tmp $(1)
	$(LINUX_DIR)/scripts/dtc/dtc -O dtb \
		-i$(dir $(1)) $(4) \
		-o $(2) $(2).tmp
	$(RM) $(2).tmp
endef

define Image/mkfs/jffs2/sub-raw
	$(STAGING_DIR_HOST)/bin/mkfs.jffs2 \
		$(2) \
		-e $(patsubst %k,%KiB,$(1)) \
		-o $@ -d $(call mkfs_target_dir,$(3)) \
		-v 2>&1 1>/dev/null | awk '/^.+$$$$/'
endef

define Image/mkfs/jffs2/sub
	$(call Image/mkfs/jffs2/sub-raw,$(1),--pad $(2),$(3))
	$(call add_jffs2_mark,$@)
endef

define Image/mkfs/jffs2/template
  Image/mkfs/jffs2-$(1) = $$(call Image/mkfs/jffs2/sub,$(1),$(JFFS2OPTS),$$(1))
  Image/mkfs/jffs2-$(1)-raw = $$(call Image/mkfs/jffs2/sub-raw,$(1),$(JFFS2OPTS),$$(1))

endef

define Image/mkfs/jffs2-nand/template
  Image/mkfs/jffs2-nand-$(1) = \
	$$(call Image/mkfs/jffs2/sub, \
		$(word 2,$(subst -, ,$(1))), \
			$(JFFS2OPTS) --no-cleanmarkers --pagesize=$(word 1,$(subst -, ,$(1))),$$(1))

endef

$(eval $(foreach S,$(JFFS2_BLOCKSIZE),$(call Image/mkfs/jffs2/template,$(S))))
$(eval $(foreach S,$(NAND_BLOCKSIZE),$(call Image/mkfs/jffs2-nand/template,$(S))))

define Image/mkfs/squashfs
	$(STAGING_DIR_HOST)/bin/mksquashfs4 $(call mkfs_target_dir,$(1)) $@ \
		-nopad -noappend -root-owned \
		-comp $(SQUASHFSCOMP) $(SQUASHFSOPT) \
		-processors $(if $(CONFIG_PKG_BUILD_JOBS),$(CONFIG_PKG_BUILD_JOBS),1) \
		$(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH))
endef

# $(1): board name
# $(2): rootfs type
# $(3): kernel image
ifneq ($(CONFIG_NAND_SUPPORT),)
   define Image/Build/SysupgradeNAND
	mkdir -p "$(KDIR_TMP)/sysupgrade-$(1)/"
	echo "BOARD=$(1)" > "$(KDIR_TMP)/sysupgrade-$(1)/CONTROL"
	[ -z "$(2)" ] || $(CP) "$(KDIR)/root.$(2)" "$(KDIR_TMP)/sysupgrade-$(1)/root"
	[ -z "$(3)" ] || $(CP) "$(3)" "$(KDIR_TMP)/sysupgrade-$(1)/kernel"
	(cd "$(KDIR_TMP)"; $(TAR) cvf \
		"$(BIN_DIR)/$(IMG_PREFIX)-$(1)-$(2)-sysupgrade.tar" sysupgrade-$(1) \
			$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
	)
   endef

# $(1) board name
# $(2) ubinize-image options (e.g. --uboot-env and/or --kernel kernelimage)
# $(3) rootfstype (e.g. squashfs or ubifs)
# $(4) options to pass-through to ubinize (i.e. $($(PROFILE)_UBI_OPTS)))
   define Image/Build/UbinizeImage
	sh $(TOPDIR)/scripts/ubinize-image.sh $(2) \
		"$(KDIR)/root.$(3)" \
		"$(KDIR)/$(IMG_PREFIX)-$(1)-$(3)-ubinized.bin" \
		$(4)
   endef

endif

define Image/mkfs/ubifs
	$(STAGING_DIR_HOST)/bin/mkfs.ubifs \
		$(UBIFS_OPTS) $(call param_unmangle,$(call param_get,fs,$(1))) \
		$(if $(CONFIG_TARGET_UBIFS_FREE_SPACE_FIXUP),--space-fixup) \
		$(if $(CONFIG_TARGET_UBIFS_COMPRESSION_NONE),--force-compr=none) \
		$(if $(CONFIG_TARGET_UBIFS_COMPRESSION_LZO),--force-compr=lzo) \
		$(if $(CONFIG_TARGET_UBIFS_COMPRESSION_ZLIB),--force-compr=zlib) \
		$(if $(shell echo $(CONFIG_TARGET_UBIFS_JOURNAL_SIZE)),--jrn-size=$(CONFIG_TARGET_UBIFS_JOURNAL_SIZE)) \
		--squash-uids \
		-o $@ -d $(call mkfs_target_dir,$(1))
endef

E2SIZE=$(shell echo $$(($(CONFIG_TARGET_ROOTFS_PARTSIZE)*1024*1024)))

define Image/mkfs/ext4
	$(STAGING_DIR_HOST)/bin/make_ext4fs \
		-l $(E2SIZE) -b $(CONFIG_TARGET_EXT4_BLOCKSIZE) \
		$(if $(CONFIG_TARGET_EXT4_RESERVED_PCT),-m $(CONFIG_TARGET_EXT4_RESERVED_PCT)) \
		$(if $(CONFIG_TARGET_EXT4_JOURNAL),,-J) \
		$(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)) \
		$@ $(call mkfs_target_dir,$(1))/
endef

define Image/Manifest
	$(STAGING_DIR_HOST)/bin/opkg \
		--offline-root $(TARGET_DIR) \
		--add-arch all:100 \
		--add-arch $(if $(ARCH_PACKAGES),$(ARCH_PACKAGES),$(BOARD)):200 list-installed > \
		$(BIN_DIR)/$(IMG_PREFIX)$(if $(PROFILE_SANITIZED),-$(PROFILE_SANITIZED)).manifest
endef

ifdef CONFIG_TARGET_ROOTFS_TARGZ
  define Image/Build/targz
	$(TAR) -cp --numeric-owner --owner=0 --group=0 --sort=name \
		$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
		-C $(TARGET_DIR)/ . | gzip -9n > $(BIN_DIR)/$(IMG_PREFIX)$(if $(PROFILE_SANITIZED),-$(PROFILE_SANITIZED))-rootfs.tar.gz
  endef
endif

ifdef CONFIG_TARGET_ROOTFS_CPIOGZ
  define Image/Build/cpiogz
	( cd $(TARGET_DIR); find . | cpio -o -H newc | gzip -9n >$(BIN_DIR)/$(IMG_PREFIX)-rootfs.cpio.gz )
  endef
endif

mkfs_packages = $(filter-out @%,$(PACKAGES_$(call param_get,pkg,pkg=$(target_params))))
mkfs_packages_add = $(filter-out -%,$(mkfs_packages))
mkfs_packages_remove = $(patsubst -%,%,$(filter -%,$(mkfs_packages)))
mkfs_cur_target_dir = $(call mkfs_target_dir,pkg=$(target_params))

opkg_target = \
	$(call opkg,$(mkfs_cur_target_dir)) \
		-f $(mkfs_cur_target_dir).conf

target-dir-%: FORCE
	rm -rf $(mkfs_cur_target_dir) $(mkfs_cur_target_dir).opkg
	$(CP) $(TARGET_DIR_ORIG) $(mkfs_cur_target_dir)
	-mv $(mkfs_cur_target_dir)/etc/opkg $(mkfs_cur_target_dir).opkg
	echo 'src default file://$(PACKAGE_DIR_ALL)' > $(mkfs_cur_target_dir).conf
	$(if $(mkfs_packages_remove), \
		-$(call opkg,$(mkfs_cur_target_dir)) remove \
			$(mkfs_packages_remove))
	$(if $(call opkg_package_files,$(mkfs_packages_add)), \
		$(opkg_target) update && \
		$(opkg_target) install \
			$(call opkg_package_files,$(mkfs_packages_add)))
	$(call prepare_rootfs,$(mkfs_cur_target_dir))
	-mv $(mkfs_cur_target_dir).opkg $(mkfs_cur_target_dir)/etc/opkg
	rm -f $(mkfs_cur_target_dir).conf

$(KDIR)/root.%: kernel_prepare
	$(call Image/mkfs/$(word 1,$(target_params)),$(target_params))

define Device/InitProfile
  PROFILES := $(PROFILE)
  DEVICE_TITLE :=
  DEVICE_PACKAGES :=
  DEVICE_DESCRIPTION = Build firmware images for $$(DEVICE_TITLE)
endef

define Device/Init
  DEVICE_NAME := $(1)
  KERNEL:=
  KERNEL_INITRAMFS = $$(KERNEL)
  KERNEL_SIZE:=
  CMDLINE:=

  IMAGES :=
  IMAGE_PREFIX := $(IMG_PREFIX)-$(1)
  IMAGE_NAME = $$(IMAGE_PREFIX)-$$(1)-$$(2)
  KERNEL_PREFIX = $$(IMAGE_PREFIX)
  KERNEL_SUFFIX := -kernel.bin
  KERNEL_INITRAMFS_SUFFIX = $$(KERNEL_SUFFIX)
  KERNEL_IMAGE = $$(KERNEL_PREFIX)$$(KERNEL_SUFFIX)
  KERNEL_INITRAMFS_PREFIX = $$(IMAGE_PREFIX)-initramfs
  KERNEL_INITRAMFS_IMAGE = $$(KERNEL_INITRAMFS_PREFIX)$$(KERNEL_INITRAMFS_SUFFIX)
  KERNEL_INITRAMFS_NAME = $$(KERNEL_NAME)-initramfs
  KERNEL_INSTALL :=
  KERNEL_NAME := vmlinux
  KERNEL_DEPENDS :=
  KERNEL_SIZE :=

  UBOOTENV_IN_UBI :=
  KERNEL_IN_UBI :=
  BLOCKSIZE :=
  PAGESIZE :=
  SUBPAGESIZE :=
  VID_HDR_OFFSET :=
  UBINIZE_OPTS :=
  UBINIZE_PARTS :=
  MKUBIFS_OPTS :=

  FS_OPTIONS/ubifs = $$(MKUBIFS_OPTS)

  DEVICE_DTS :=
  DEVICE_DTS_DIR :=

  BOARD_NAME :=
  UIMAGE_NAME :=
  SUPPORTED_DEVICES :=
  IMAGE_METADATA :=

  FILESYSTEMS := $(TARGET_FILESYSTEMS)
endef

DEFAULT_DEVICE_VARS := \
  DEVICE_NAME KERNEL KERNEL_INITRAMFS KERNEL_SIZE KERNEL_INITRAMFS_IMAGE \
  DEVICE_DTS DEVICE_DTS_DIR BOARD_NAME CMDLINE \
  UBOOTENV_IN_UBI KERNEL_IN_UBI \
  BLOCKSIZE PAGESIZE SUBPAGESIZE VID_HDR_OFFSET \
  UBINIZE_OPTS UIMAGE_NAME UBINIZE_PARTS \
  SUPPORTED_DEVICES IMAGE_METADATA

define Device/ExportVar
  $(1) : $(2):=$$($(2))

endef
define Device/Export
  $(foreach var,$(DEVICE_VARS) $(DEFAULT_DEVICE_VARS),$(call Device/ExportVar,$(1),$(var)))
  $(1) : FILESYSTEM:=$(2)
endef

ifdef IB
  DEVICE_CHECK_PROFILE = $(filter $(1),DEVICE_$(PROFILE) $(PROFILE))
else
  DEVICE_CHECK_PROFILE = $(CONFIG_TARGET_$(if $(CONFIG_TARGET_MULTI_PROFILE),DEVICE_)$(call target_conf,$(BOARD)$(if $(SUBTARGET),_$(SUBTARGET)))_$(1))
endif

DEVICE_EXTRA_PACKAGES = $(call qstrip,$(CONFIG_TARGET_DEVICE_PACKAGES_$(call target_conf,$(BOARD)$(if $(SUBTARGET),_$(SUBTARGET)))_DEVICE_$(1)))

define merge_packages
  $(1) :=
  $(foreach pkg,$(2),
    $(1) := $$(strip $$(filter-out -$$(patsubst -%,%,$(pkg)) $$(patsubst -%,%,$(pkg)),$$($(1))) $(pkg))
  )
endef

define Device/Check/Common
  _PROFILE_SET = $$(strip $$(foreach profile,$$(PROFILES) DEVICE_$(1),$$(call DEVICE_CHECK_PROFILE,$$(profile))))
  ifdef TARGET_PER_DEVICE_ROOTFS
    $$(eval $$(call merge_packages,_PACKAGES,$$(DEVICE_PACKAGES) $$(call DEVICE_EXTRA_PACKAGES,$(1))))
    ROOTFS_ID/$(1) := $$(if $$(_PROFILE_SET),$$(call mkfs_packages_id,$$(_PACKAGES)))
    PACKAGES_$$(ROOTFS_ID/$(1)) := $$(_PACKAGES)
  endif
endef

define Device/Check
  $(Device/Check/Common)
  KDIR_KERNEL_IMAGE := $(KDIR)/$(1)$$(KERNEL_SUFFIX)
  _TARGET := $$(if $$(_PROFILE_SET),install-images,install-disabled)
  ifndef IB
    _COMPILE_TARGET := $$(if $(CONFIG_IB)$$(_PROFILE_SET),compile,compile-disabled)
  endif
endef

ifndef IB
define Device/Build/initramfs
  $(call Device/Export,$(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE),$(1))
  $$(_TARGET): $$(if $$(KERNEL_INITRAMFS),$(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE))

  $(KDIR)/$$(KERNEL_INITRAMFS_NAME):: image_prepare
  $(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE)
	cp $$^ $$@

  $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/$$(KERNEL_INITRAMFS_NAME) $(CURDIR)/Makefile $$(KERNEL_DEPENDS)
	@rm -f $$@
	$$(call concat_cmd,$$(KERNEL_INITRAMFS))
endef
endif

define Device/Build/compile
  $$(_COMPILE_TARGET): $(KDIR)/$(1)
  $(eval $(call Device/Export,$(KDIR)/$(1)))
  $(KDIR)/$(1):
	$$(call concat_cmd,$(COMPILE/$(1)))

endef

define Device/Build/kernel
  $(KDIR)/$$(KERNEL_NAME):: image_prepare
  $$(_TARGET): $$(if $$(KERNEL_INSTALL),$(BIN_DIR)/$$(KERNEL_IMAGE))
  $(call Device/Export,$$(KDIR_KERNEL_IMAGE),$(1))
  $(BIN_DIR)/$$(KERNEL_IMAGE): $$(KDIR_KERNEL_IMAGE)
	cp $$^ $$@
  ifndef IB
    ifdef CONFIG_IB
      install: $$(KDIR_KERNEL_IMAGE)
    endif
    $$(KDIR_KERNEL_IMAGE): $(KDIR)/$$(KERNEL_NAME) $(CURDIR)/Makefile $$(KERNEL_DEPENDS)
	@rm -f $$@
	$$(call concat_cmd,$$(KERNEL))
	$$(if $$(KERNEL_SIZE),$$(call Build/check-size,$$(KERNEL_SIZE)))
  endif
endef

define Device/Build/image
  $$(_TARGET): $(BIN_DIR)/$(call IMAGE_NAME,$(1),$(2))
  $(eval $(call Device/Export,$(KDIR)/tmp/$(call IMAGE_NAME,$(1),$(2)),$(1)))
  ROOTFS/$(1)/$(3) := \
	$(KDIR)/root.$(1)$$(strip \
		$$(if $$(FS_OPTIONS/$(1)),+fs=$$(call param_mangle,$$(FS_OPTIONS/$(1)))) \
	)$$(strip \
		$(if $(TARGET_PER_DEVICE_ROOTFS),+pkg=$$(ROOTFS_ID/$(3))) \
	)
  ifndef IB
    $$(ROOTFS/$(1)/$(3)): $(if $(TARGET_PER_DEVICE_ROOTFS),target-dir-$$(ROOTFS_ID/$(3)))
  endif
  $(KDIR)/tmp/$(call IMAGE_NAME,$(1),$(2)): $$(KDIR_KERNEL_IMAGE) $$(ROOTFS/$(1)/$(3))
	@rm -f $$@
	[ -f $$(word 1,$$^) -a -f $$(word 2,$$^) ]
	$$(call concat_cmd,$(if $(IMAGE/$(2)/$(1)),$(IMAGE/$(2)/$(1)),$(IMAGE/$(2))))

  .IGNORE: $(BIN_DIR)/$(call IMAGE_NAME,$(1),$(2))
  $(BIN_DIR)/$(call IMAGE_NAME,$(1),$(2)): $(KDIR)/tmp/$(call IMAGE_NAME,$(1),$(2))
	cp $$^ $$@

endef

define Device/Build
  $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(call Device/Build/initramfs,$(1)))
  $(call Device/Build/kernel,$(1))

  $$(eval $$(foreach compile,$$(COMPILE), \
    $$(call Device/Build/compile,$$(compile),$(1))))

  $$(eval $$(foreach image,$$(IMAGES), \
    $$(foreach fs,$$(filter $(TARGET_FILESYSTEMS),$$(FILESYSTEMS)), \
      $$(call Device/Build/image,$$(fs),$$(image),$(1)))))
endef

define Device/DumpInfo
Target-Profile: DEVICE_$(1)
Target-Profile-Name: $(DEVICE_TITLE)
Target-Profile-Packages: $(DEVICE_PACKAGES)
Target-Profile-Description:
$(DEVICE_DESCRIPTION)
@@

endef

define Device/Dump
$$(eval $$(if $$(DEVICE_TITLE),$$(info $$(call Device/DumpInfo,$(1)))))
endef

define Device
  $(call Device/InitProfile,$(1))
  $(call Device/Init,$(1))
  $(call Device/Default,$(1))
  $(call Device/$(1),$(1))
  $(call Device/Check,$(1))
  $(call Device/$(if $(DUMP),Dump,Build),$(1))

endef

define BuildImage

  ifneq ($(DUMP),)
    all: dumpinfo
    dumpinfo: FORCE
	@true
  endif

  download:
  prepare:
  compile:
  clean:
  legacy-images-prepare:
  legacy-images:
  image_prepare:

  ifeq ($(IB),)
    .PHONY: download prepare compile clean image_prepare kernel_prepare install install-images
    compile:
		$(call Build/Compile)

    clean:
		$(call Build/Clean)

    image_prepare: compile
		mkdir -p $(BIN_DIR) $(KDIR)/tmp
		$(call Image/Prepare)

    legacy-images-prepare-make: image_prepare
		$(MAKE) legacy-images-prepare

  else
    image_prepare:
		mkdir -p $(BIN_DIR) $(KDIR)/tmp
  endif

  kernel_prepare: image_prepare
	$(call Image/Build/targz)
	$(call Image/Build/cpiogz)
	$(call Image/BuildKernel)
	$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(if $(IB),,$(call Image/BuildKernel/Initramfs)))
	$(call Image/InstallKernel)

  $(foreach device,$(TARGET_DEVICES),$(call Device,$(device)))
  $(foreach device,$(LEGACY_DEVICES),$(call LegacyDevice,$(device)))

  install-images: kernel_prepare $(foreach fs,$(filter-out $(if $(UBIFS_OPTS),,ubifs),$(TARGET_FILESYSTEMS) $(fs-subtypes-y)),$(KDIR)/root.$(fs))
	$(foreach fs,$(TARGET_FILESYSTEMS),
		$(call Image/Build,$(fs))
	)

  legacy-images-make: install-images
	$(call Image/mkfs/ubifs/legacy)
	$(MAKE) legacy-images

  install: install-images
	$(call Image/Manifest)

endef