opkg: add update-alternatives support
authorYousong Zhou <yszhou4tech@gmail.com>
Sat, 4 Mar 2017 11:35:37 +0000 (19:35 +0800)
committerYousong Zhou <yszhou4tech@gmail.com>
Sun, 5 Mar 2017 09:23:45 +0000 (17:23 +0800)
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
package/system/opkg/Makefile
package/system/opkg/files/update-alternatives [new file with mode: 0755]

index fbf87cb..56f5cce 100644 (file)
@@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/version.mk
 include $(INCLUDE_DIR)/feeds.mk
 
 PKG_NAME:=opkg
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 PKG_FLAGS:=essential
 
 PKG_SOURCE_PROTO:=git
@@ -94,6 +94,9 @@ define Package/opkg/install
   endif
        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_BIN) ./files/opkg-key $(1)/usr/sbin/
+       $(INSTALL_BIN) ./files/update-alternatives $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/config
+       touch $(1)/etc/config/opkg
 endef
 
 define Host/Install
diff --git a/package/system/opkg/files/update-alternatives b/package/system/opkg/files/update-alternatives
new file mode 100755 (executable)
index 0000000..6a8f18b
--- /dev/null
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+usage() {
+       cat <<EOF
+Usage: $0 update|remove --spec <prio>:<path>:<alt-path>
+
+EOF
+       exit 1
+}
+
+errmsg() {
+       echo "$0: $@" >&2
+}
+
+uci_() {
+       $UCI ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} "$@"
+}
+
+check_path() {
+       local path="${IPKG_INSTROOT}$1"
+
+       [ -L "$path" -o ! -e "$path" ] || {
+               errmsg "$0: $path exists and is not an symbolic file"
+               exit 1
+       }
+}
+
+update_path() {
+       local path="$1"
+       local found_section found_altpath
+       local found_prio=-1 found_prio_altpath
+       local IFS cur altpath
+
+       config_load opkg
+       config_foreach find_path alternatives "$prio" "$path"
+       if [ -n "$found_prio_altpath" ]; then
+               IFS=:; set -- $found_prio_altpath; altpath=$2; IFS="$oIFS"
+               cur="$(readlink -f "$path")"
+               if [ "$cur" != "$altpath" ]; then
+                       errmsg "link $path -> $altpath"
+                       ln -sf "$altpath" "${IPKG_INSTROOT}$path"
+               fi
+       elif [ -n "$found_section" ]; then
+               errmsg "remove empty alternatives section for $path"
+               uci_ delete "opkg.$found_section"
+               uci_ commit opkg
+               rm -f "${IPKG_INSTROOT}$path"
+       fi
+}
+
+find_altpath() {
+       local cfgaltpath="$1"
+       local cfg="$2"
+       local prio="$3"
+       local altpath="$4"
+       local cfgprio cfgaltpath_
+       local oIFS="$IFS"; IFS=:; set -- $cfgaltpath; cfgprio="$1"; cfgaltpath_="$2"; IFS="$oIFS"
+
+       if [ "$cfgaltpath_" = "$altpath" ]; then
+               found_altpath="$cfgaltpath"
+       fi
+       if [ "$cfgprio" -gt "$found_prio" ]; then
+               found_prio="$cfgprio"
+               found_prio_altpath="$cfgaltpath"
+       fi
+}
+
+find_path() {
+       local cfg="$1"
+       local prio="$2"
+       local path="$3"
+       local altpath="$4"
+       local cfgpath
+
+       config_get cfgpath "$cfg" path
+       [ "$cfgpath" = "$path" ] || return
+       found_section="$cfg"
+       config_list_foreach "$cfg" altpath find_altpath "$cfg" "$prio" "$altpath"
+}
+
+cmd_update() {
+       local spec="$1"
+       local prio path altpath
+       local oIFS="$IFS"
+       local found_section found_altpath
+       local found_prio=-1 found_prio_altpath
+
+       IFS=:; set -- $spec; IFS="$oIFS"
+       prio="$1"
+       path="$2"
+       altpath="$3"
+       check_path "$path"
+       if [ ! -e "${IPKG_INSTROOT}$altpath" ]; then
+               errmsg "$altpath does not exist"
+               return 1
+       fi
+
+       config_load opkg
+       config_foreach find_path alternatives "$prio" "$path" "$altpath"
+       if [ -z "$found_section" ]; then
+               found_section="$(uci_ add opkg alternatives)"
+               uci_ set opkg.$found_section.path=$path
+       fi
+       if [ -n "$found_altpath" ]; then
+               if [ "$found_altpath" != "$prio:$altpath" ]; then
+                       # update priority
+                       uci_ del_list opkg.$found_section.altpath=$found_altpath
+                       uci_ add_list opkg.$found_section.altpath=$prio:$altpath
+               fi
+       else
+               uci_ add_list opkg.$found_section.altpath=$prio:$altpath
+       fi
+       uci_ commit opkg
+       update_path "$path"
+}
+
+cmd_remove() {
+       local spec="$1"
+       local prio path altpath
+       local oIFS="$IFS"
+       local found_section found_altpath
+       local found_prio=-1 found_prio_altpath
+
+       IFS=:; set -- $spec; IFS="$oIFS"
+       prio="$1"
+       path="$2"
+       altpath="$3"
+       check_path "$path"
+
+       config_load opkg
+       config_foreach find_path alternatives "$prio" "$path" "$altpath"
+       if [ -n "$found_section" -a -n "$found_altpath" ]; then
+               uci_ del_list opkg.$found_section.altpath=$found_altpath
+               uci_ commit opkg
+               update_path "$path"
+       else
+               errmsg "spec $spec not found"
+       fi
+}
+
+. ${IPKG_INSTROOT}/lib/functions.sh
+
+UCI="${UCI:-/sbin/uci}"
+UCI_STATE_DIR="${IPKG_INSTROOT}/var/state"
+ARG_CMD=
+ARG_SPEC=
+while [ "$#" -gt 0 ]; do
+       case "$1" in
+               update|remove)
+                       ARG_CMD="$1"
+                       shift
+                       ;;
+               --spec)
+                       ARG_SPEC="$2";
+                       shift 2
+                       ;;
+               *) usage ;;
+       esac
+done
+
+[ -n "$ARG_CMD" -a -n "$ARG_SPEC" ] || usage
+
+cmd_$ARG_CMD "$ARG_SPEC"