opkg: add update-alternatives support
[openwrt/staging/yousong.git] / package / system / opkg / files / update-alternatives
1 #!/bin/sh
2
3 usage() {
4 cat <<EOF
5 Usage: $0 update|remove --spec <prio>:<path>:<alt-path>
6
7 EOF
8 exit 1
9 }
10
11 errmsg() {
12 echo "$0: $@" >&2
13 }
14
15 uci_() {
16 $UCI ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} "$@"
17 }
18
19 check_path() {
20 local path="${IPKG_INSTROOT}$1"
21
22 [ -L "$path" -o ! -e "$path" ] || {
23 errmsg "$0: $path exists and is not an symbolic file"
24 exit 1
25 }
26 }
27
28 update_path() {
29 local path="$1"
30 local found_section found_altpath
31 local found_prio=-1 found_prio_altpath
32 local IFS cur altpath
33
34 config_load opkg
35 config_foreach find_path alternatives "$prio" "$path"
36 if [ -n "$found_prio_altpath" ]; then
37 IFS=:; set -- $found_prio_altpath; altpath=$2; IFS="$oIFS"
38 cur="$(readlink -f "$path")"
39 if [ "$cur" != "$altpath" ]; then
40 errmsg "link $path -> $altpath"
41 ln -sf "$altpath" "${IPKG_INSTROOT}$path"
42 fi
43 elif [ -n "$found_section" ]; then
44 errmsg "remove empty alternatives section for $path"
45 uci_ delete "opkg.$found_section"
46 uci_ commit opkg
47 rm -f "${IPKG_INSTROOT}$path"
48 fi
49 }
50
51 find_altpath() {
52 local cfgaltpath="$1"
53 local cfg="$2"
54 local prio="$3"
55 local altpath="$4"
56 local cfgprio cfgaltpath_
57 local oIFS="$IFS"; IFS=:; set -- $cfgaltpath; cfgprio="$1"; cfgaltpath_="$2"; IFS="$oIFS"
58
59 if [ "$cfgaltpath_" = "$altpath" ]; then
60 found_altpath="$cfgaltpath"
61 fi
62 if [ "$cfgprio" -gt "$found_prio" ]; then
63 found_prio="$cfgprio"
64 found_prio_altpath="$cfgaltpath"
65 fi
66 }
67
68 find_path() {
69 local cfg="$1"
70 local prio="$2"
71 local path="$3"
72 local altpath="$4"
73 local cfgpath
74
75 config_get cfgpath "$cfg" path
76 [ "$cfgpath" = "$path" ] || return
77 found_section="$cfg"
78 config_list_foreach "$cfg" altpath find_altpath "$cfg" "$prio" "$altpath"
79 }
80
81 cmd_update() {
82 local spec="$1"
83 local prio path altpath
84 local oIFS="$IFS"
85 local found_section found_altpath
86 local found_prio=-1 found_prio_altpath
87
88 IFS=:; set -- $spec; IFS="$oIFS"
89 prio="$1"
90 path="$2"
91 altpath="$3"
92 check_path "$path"
93 if [ ! -e "${IPKG_INSTROOT}$altpath" ]; then
94 errmsg "$altpath does not exist"
95 return 1
96 fi
97
98 config_load opkg
99 config_foreach find_path alternatives "$prio" "$path" "$altpath"
100 if [ -z "$found_section" ]; then
101 found_section="$(uci_ add opkg alternatives)"
102 uci_ set opkg.$found_section.path=$path
103 fi
104 if [ -n "$found_altpath" ]; then
105 if [ "$found_altpath" != "$prio:$altpath" ]; then
106 # update priority
107 uci_ del_list opkg.$found_section.altpath=$found_altpath
108 uci_ add_list opkg.$found_section.altpath=$prio:$altpath
109 fi
110 else
111 uci_ add_list opkg.$found_section.altpath=$prio:$altpath
112 fi
113 uci_ commit opkg
114 update_path "$path"
115 }
116
117 cmd_remove() {
118 local spec="$1"
119 local prio path altpath
120 local oIFS="$IFS"
121 local found_section found_altpath
122 local found_prio=-1 found_prio_altpath
123
124 IFS=:; set -- $spec; IFS="$oIFS"
125 prio="$1"
126 path="$2"
127 altpath="$3"
128 check_path "$path"
129
130 config_load opkg
131 config_foreach find_path alternatives "$prio" "$path" "$altpath"
132 if [ -n "$found_section" -a -n "$found_altpath" ]; then
133 uci_ del_list opkg.$found_section.altpath=$found_altpath
134 uci_ commit opkg
135 update_path "$path"
136 else
137 errmsg "spec $spec not found"
138 fi
139 }
140
141 . ${IPKG_INSTROOT}/lib/functions.sh
142
143 UCI="${UCI:-/sbin/uci}"
144 UCI_STATE_DIR="${IPKG_INSTROOT}/var/state"
145 ARG_CMD=
146 ARG_SPEC=
147 while [ "$#" -gt 0 ]; do
148 case "$1" in
149 update|remove)
150 ARG_CMD="$1"
151 shift
152 ;;
153 --spec)
154 ARG_SPEC="$2";
155 shift 2
156 ;;
157 *) usage ;;
158 esac
159 done
160
161 [ -n "$ARG_CMD" -a -n "$ARG_SPEC" ] || usage
162
163 cmd_$ARG_CMD "$ARG_SPEC"