mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-30 12:25:13 +08:00
update 2026-09-24 16:56:26
This commit is contained in:
1 parent
b31a5c3878
commit
e4cee331e9
6885 files changed
+3240523
No files matched your search
@@ -0,0 +1,161 @@
|
||||
### 路由器端API:
|
||||
0. 获取csrfToken(用于POST请求)
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/token
|
||||
|
||||
|
||||
{"token":"xxx"}
|
||||
```
|
||||
1. 已安装软件列表
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/installed
|
||||
|
||||
|
||||
[
|
||||
{
|
||||
"description": "DDNS.TO内网穿透",
|
||||
"tags": [
|
||||
"net",
|
||||
"tool"
|
||||
],
|
||||
"entry": "/cgi-bin/luci/admin/services/ddnsto",
|
||||
"author": "xiaobao",
|
||||
"depends": [
|
||||
"ddnsto",
|
||||
"luci-app-ddnsto",
|
||||
"luci-i18n-ddnsto-zh-cn"
|
||||
],
|
||||
"title": "DDNS.TO",
|
||||
"time": 1629356347,
|
||||
"release": 1,
|
||||
"website": "https://www.ddnsto.com/",
|
||||
"name": "ddnsto",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
]
|
||||
```
|
||||
2. 安装软件
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/install
|
||||
token=xxx&package=upnp&autoconf=1&path=/mnt/nvme&enable=1
|
||||
|
||||
autoconf=1&path=/mnt/nvme&enable=1 是可选参数,表示安装完以后是否自动配置插件
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
3. 更新软件
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/upgrade
|
||||
token=xxx&package=upnp
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
4. 卸载软件
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/remove
|
||||
token=xxx&package=upnp
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
5. 刷新可用软件列表
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/update
|
||||
token=xxx
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
6. 查询特定软件状态
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/status?package=ddnsto
|
||||
|
||||
|
||||
{
|
||||
"description": "DDNS.TO内网穿透",
|
||||
"tags": [
|
||||
"net",
|
||||
"tool"
|
||||
],
|
||||
"entry": "/cgi-bin/luci/admin/services/ddnsto",
|
||||
"author": "xiaobao",
|
||||
"depends": [
|
||||
"ddnsto",
|
||||
"luci-app-ddnsto",
|
||||
"luci-i18n-ddnsto-zh-cn"
|
||||
],
|
||||
"installed": true,
|
||||
"title": "DDNS.TO",
|
||||
"time": "1629356347",
|
||||
"release": 1,
|
||||
"website": "https://www.ddnsto.com/",
|
||||
"name": "ddnsto",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
|
||||
{"installed":false}
|
||||
```
|
||||
7. 任务状态(日志),已废弃,使用luci-lib-taskd提供的封装
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/log
|
||||
|
||||
|
||||
{
|
||||
"stdout": "Installing app-meta-ddnsto (1.0.0) to root...\nDownloading http://192.168.9.168:9999/packages/aarch64_cortex-a53/meta/app-meta-ddnsto_1.0.0_all.ipk\nConfiguring app-meta-ddnsto.\n",
|
||||
"stderr": "",
|
||||
"code": 206
|
||||
}
|
||||
|
||||
{"stdout":"","stderr":"","code":0}
|
||||
```
|
||||
8. 上传安装
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/upload
|
||||
|
||||
|
||||
(文件上传表单,支持文件扩展名".ipk,.run")
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
|
||||
9. 检查iStore自身更新
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/check_self_upgrade
|
||||
|
||||
|
||||
{"code":500, "msg":"Internal Error"}
|
||||
{"code":200, "msg":"1.1.2"}
|
||||
{"code":304, "msg":""}
|
||||
```
|
||||
|
||||
1. 更新iStore自身
|
||||
> 检查iStore自身更新接口返回code为200时才调用这个接口
|
||||
```
|
||||
POST /cgi-bin/luci/admin/store/do_self_upgrade
|
||||
token=xxx
|
||||
|
||||
|
||||
{"code":0, "stdout":"", "stderr":""}
|
||||
```
|
||||
|
||||
2. 枚举块设备
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/get_block_devices
|
||||
|
||||
|
||||
{"code":500, "msg":"Unable to execute block utility"}
|
||||
{"code":200, "data":{"sda1":{"dev":"\/dev\/sda1","uuid":"f54566dd-ec58-4e24-9451-bbf75834add3","version":"1.0","type":"ext4","size":"238.46 GB"},"mmcblk0p2":{"dev":"\/dev\/mmcblk0p2","uuid":"dba3d0dc-f072-4e81-a0ac-ac35197fb286","version":"1.0","label":"etc","mount":"\/overlay","type":"ext4","size":"6.87 GB"},"mmcblk0p1":{"dev":"\/dev\/mmcblk0p1","uuid":"8f9564a1-68006e25-c4c26df6-de88ef16","version":"4.0","mount":"\/rom","type":"squashfs","size":"127.99 MB"}}}
|
||||
```
|
||||
|
||||
3. 检查插件是否已经配置过
|
||||
```
|
||||
GET /cgi-bin/luci/admin/store/configured?uci=ddnsto
|
||||
|
||||
uci参数是uci配置文件的名称,不是包名,不过大部分情况下都是一致的。
|
||||
|
||||
{"code":200}
|
||||
{"code":200, "configured":true}
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
# Copyright (C) 2016 Openwrt.org
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI based ipk/apk store
|
||||
LUCI_DESCRIPTION:=luci-app-store is a ipk/apk store developed by LinkEase team
|
||||
LUCI_DEPENDS:=+curl +tar +libuci-lua +mount-utils +luci-lib-taskd
|
||||
|
||||
LUCI_EXTRA_DEPENDS:=luci-lib-taskd (>=1.0.19)
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_VERSION:=0.2.1-r1
|
||||
# PKG_RELEASE MUST be empty for luci.mk
|
||||
PKG_RELEASE:=
|
||||
|
||||
ISTORE_UI_VERSION:=0.2.0
|
||||
ISTORE_UI_RELEASE:=2
|
||||
PKG_HASH:=9aec741aa5675347bc5a818acb285901bddf309af8ae402dd898336751de38be
|
||||
|
||||
PKG_SOURCE_URL_FILE:=v$(ISTORE_UI_VERSION)-$(ISTORE_UI_RELEASE).tar.gz
|
||||
PKG_SOURCE:=istore-ui-$(PKG_SOURCE_URL_FILE)
|
||||
PKG_SOURCE_URL:=https://github.com/linkease/istore-ui/archive/refs/tags
|
||||
|
||||
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
|
||||
|
||||
TARGET_CONFIGURE_OPTS= FRONTEND_DIST="$(BUILD_DIR)/istore-ui-$(ISTORE_UI_VERSION)-$(ISTORE_UI_RELEASE)/app-store-ui/src/dist" APP_STORE_VERSION="$(PKG_VERSION)"
|
||||
TARGET_CONFIGURE_OPTS+= SED="$(SED)"
|
||||
TARGET_CONFIGURE_OPTS+= USE_APK="$(CONFIG_USE_APK)"
|
||||
|
||||
define Package/luci-app-store/conffiles
|
||||
/etc/.app_store.id
|
||||
/etc/config/istore
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# luci-app-store
|
||||
OpenWRT应用商店
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,64 @@
|
||||
<%+header%>
|
||||
<%
|
||||
local jsonc = require "luci.jsonc"
|
||||
%>
|
||||
<script>
|
||||
(function(){
|
||||
var vue_prefix="<%=prefix%>";
|
||||
var myurl = window.location.pathname;
|
||||
window.addEventListener('popstate', function(){
|
||||
if (myurl != window.location.pathname
|
||||
&& window.location.pathname != vue_prefix
|
||||
&& ! window.location.pathname.startsWith(vue_prefix+'/')) {
|
||||
window.location.href = window.location.pathname;
|
||||
}
|
||||
});
|
||||
window.vue_base = vue_prefix + '/';
|
||||
// window.istore_api_base = "https://istore.istoreos.com";
|
||||
// window.istore_icon_base = "https://istore.linkease.com.cdn.koolcenter.com";
|
||||
window.vue_lang_data = '/luci-static/istore/i18n/<%=lang%>.json?v=<%=id.version%>';
|
||||
window.vue_lang = '<%=lang%>';
|
||||
window.token = "<%=token%>";
|
||||
window.device_id = {arch:"<%=id.arch%>",uid:"<%=id.uid%>",version:"<%=id.version%>"};
|
||||
window.istore_features = <%=jsonc.stringify(features)%>.filter(f => f !== '_lua_force_array_');
|
||||
window.istore_config = <%=jsonc.stringify(user_config or {})%>;
|
||||
})();
|
||||
</script>
|
||||
<h2 name="content"><%:iStore%>
|
||||
<a onclick="void(0)" href="https://github.com/linkease/istore/issues/22" target="_blank" style="text-decoration: none;">
|
||||
v<%=id.version%>
|
||||
</a>
|
||||
</h2>
|
||||
<link rel="stylesheet" href="/luci-static/istore/style.css?v=<%=id.version%>">
|
||||
<div id="app">
|
||||
</div>
|
||||
<%+tasks/embed%>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
let beforeunloadRegistered = false;
|
||||
taskd.show_mask_on_stopped = true;
|
||||
window.istore_log = function(flush_menu_onclose, onExit) {
|
||||
if (flush_menu_onclose && !beforeunloadRegistered) {
|
||||
beforeunloadRegistered = true;
|
||||
window.addEventListener("beforeunload", function(event) {
|
||||
try { window.L.ui.menu.flushCache() } catch (e) { }
|
||||
return true;
|
||||
});
|
||||
}
|
||||
taskd.show_log("istore", true, onExit);
|
||||
};
|
||||
})();
|
||||
<%
|
||||
local taskd = require "luci.model.tasks"
|
||||
local status = taskd.status("istore")
|
||||
if status.running or status.exit_code ~= 404 then
|
||||
-%>
|
||||
window.istore_log(true);
|
||||
<%
|
||||
end
|
||||
%>
|
||||
</script>
|
||||
|
||||
<script type="module" crossorigin src="/luci-static/istore/index.js?v=<%=id.version%>"></script>
|
||||
<%+footer%>
|
||||
Executable
+564
@@ -0,0 +1,564 @@
|
||||
#!/bin/sh
|
||||
# this script MUST supports executting without luci-app-store installed,
|
||||
# so we can use this script to install luci-app-store itself
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
if [ "${action:0:9}" = "AUTOCONF=" ]; then
|
||||
export "ISTORE_${action}"
|
||||
exec "$0" "$@"
|
||||
fi
|
||||
|
||||
IS_ROOT=/tmp/is-root
|
||||
TMP_SELF_COPY=/var/run/cloned-is-opkg
|
||||
USE_APK=false
|
||||
DISABLE_MIRROR=false
|
||||
if [[ -s /etc/apk/arch ]]; then
|
||||
USE_APK=true
|
||||
fi
|
||||
|
||||
if $USE_APK; then
|
||||
LISTS_DIR=${IS_ROOT}/apk
|
||||
APK_CONF=${IS_ROOT}/etc/apk.conf
|
||||
FEEDS_SERVER=https://istore.istoreos.com/repo-apk
|
||||
FEEDS_SERVER_MIRRORS="https://repo.istoreos.com/repo-apk"
|
||||
ISTORE_INDEX=$FEEDS_SERVER/all/store/packages.adb
|
||||
META_DIR=/lib/apk
|
||||
|
||||
ARCH=`cat /rom/etc/apk/arch /etc/apk/arch 2>/dev/null | head -1`
|
||||
else
|
||||
LISTS_DIR_O=/tmp/opkg-lists
|
||||
LISTS_DIR=${IS_ROOT}${LISTS_DIR_O}
|
||||
OPKG_CONF_DIR=${IS_ROOT}/etc/opkg
|
||||
OPKG_CONF_DIR_M=${IS_ROOT}/etc/opkg_m
|
||||
FEEDS_SERVER=https://istore.istoreos.com/repo
|
||||
FEEDS_SERVER_MIRRORS="https://repo.istoreos.com/repo"
|
||||
ISTORE_INDEX=$FEEDS_SERVER/all/store/Packages.gz
|
||||
META_DIR=/usr/lib/opkg
|
||||
|
||||
ARCH=`sed -n -e 's/^Architecture: *\([^ ]\+\) *$/\1/p' /rom/usr/lib/opkg/info/libc.control /usr/lib/opkg/info/libc.control 2>/dev/null | head -1`
|
||||
fi
|
||||
|
||||
# for istore self upgrade
|
||||
ISTORE_PKG=luci-app-store
|
||||
ISTORE_DEP_PKGS="luci-lib-taskd luci-lib-xterm taskd"
|
||||
|
||||
NEWLINE=$'\n'
|
||||
|
||||
is_init() {
|
||||
mkdir -p ${LISTS_DIR} ${IS_ROOT}/etc ${IS_ROOT}/var
|
||||
if $USE_APK; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat /etc/opkg.conf | grep -Fv lists_dir | grep -Fv check_signature > ${IS_ROOT}/etc/opkg.conf
|
||||
|
||||
cp ${IS_ROOT}/etc/opkg.conf ${IS_ROOT}/etc/opkg_o.conf
|
||||
|
||||
echo >> ${IS_ROOT}/etc/opkg.conf
|
||||
echo "lists_dir ext ${LISTS_DIR}" >> ${IS_ROOT}/etc/opkg.conf
|
||||
# create opkg_o.conf for executting 'opkg update' with offline-root, so we don't overwrite system opkg list
|
||||
echo >> ${IS_ROOT}/etc/opkg_o.conf
|
||||
echo "lists_dir ext ${LISTS_DIR_O}" >> ${IS_ROOT}/etc/opkg_o.conf
|
||||
|
||||
cp -au /etc/opkg ${IS_ROOT}/etc/
|
||||
[ -e ${IS_ROOT}/var/lock ] || ln -s /var/lock ${IS_ROOT}/var/lock
|
||||
}
|
||||
|
||||
apk_wrap() {
|
||||
APK_CONFIG=${APK_CONF} apk "$@"
|
||||
}
|
||||
|
||||
opkg_wrap() {
|
||||
OPKG_CONF_DIR=${OPKG_CONF_DIR} opkg -f ${IS_ROOT}/etc/opkg.conf "$@"
|
||||
}
|
||||
|
||||
simple_apk_opkg() {
|
||||
local action="$1"
|
||||
shift
|
||||
if $USE_APK; then
|
||||
case "$action" in
|
||||
"install")
|
||||
action=add
|
||||
;;
|
||||
"remove")
|
||||
action=del
|
||||
;;
|
||||
esac
|
||||
apk_wrap "$action" "$@"
|
||||
else
|
||||
opkg_wrap "$action" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
do_in_mirrors() {
|
||||
local server
|
||||
if ! $DISABLE_MIRROR; then
|
||||
local newpath="/usr/libexec/istore/mirror-bin:$PATH"
|
||||
for server in $FEEDS_SERVER_MIRRORS ; do
|
||||
echo "Try mirror server $server"
|
||||
PATH="$newpath" IS_ORIG_SERVER=$FEEDS_SERVER IS_MIRROR_SERVER=$server "$@" && return 0
|
||||
done
|
||||
DISABLE_MIRROR=true
|
||||
fi
|
||||
echo "Try origin server $FEEDS_SERVER"
|
||||
"$@"
|
||||
}
|
||||
|
||||
apk_wrap_mirrors() {
|
||||
do_in_mirrors apk_wrap "$@"
|
||||
}
|
||||
|
||||
opkg_wrap_mirrors() {
|
||||
do_in_mirrors opkg_wrap "$@"
|
||||
}
|
||||
|
||||
do_install_in_mirrors() {
|
||||
if $USE_APK; then
|
||||
apk_wrap_mirrors add "$@"
|
||||
else
|
||||
opkg_wrap_mirrors install "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
do_upgrade_in_mirrors() {
|
||||
if $USE_APK; then
|
||||
apk_wrap_mirrors upgrade "$@"
|
||||
else
|
||||
opkg_wrap_mirrors upgrade "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
alias fcurl='curl -L --fail --show-error'
|
||||
|
||||
check_space() {
|
||||
local free="$((`df -kP / | awk 'NR==2 {print $4}'` >> 10 ))"
|
||||
if [ "$free" -lt 1 ]; then
|
||||
echo "Root disk full!" >&2
|
||||
exit 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
update() {
|
||||
if [ -z "${ARCH}" ]; then
|
||||
echo "Get architecture failed" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Fetch feed list for ${ARCH}"
|
||||
if $USE_APK; then
|
||||
rm -rf ${IS_ROOT}/var/tmp ${IS_ROOT}/etc/arch ${IS_ROOT}/etc/istore.pem
|
||||
mkdir -p ${IS_ROOT}/var/tmp
|
||||
fcurl --no-progress-meter -o ${IS_ROOT}/var/tmp/meta.conf "${FEEDS_SERVER}/all/meta.conf" && \
|
||||
fcurl --no-progress-meter -o ${IS_ROOT}/var/tmp/all.conf "${FEEDS_SERVER}/all/isfeeds.conf" && \
|
||||
fcurl --no-progress-meter -o ${IS_ROOT}/var/tmp/arch.conf "${FEEDS_SERVER}/${ARCH}/isfeeds.conf" && \
|
||||
fcurl --no-progress-meter -o ${IS_ROOT}/etc/arch "${FEEDS_SERVER}/${ARCH}/archlist.conf" || \
|
||||
return 1
|
||||
echo "cache-dir $LISTS_DIR" > ${APK_CONF}
|
||||
cat ${IS_ROOT}/var/tmp/arch.conf ${IS_ROOT}/var/tmp/all.conf ${IS_ROOT}/var/tmp/meta.conf >> ${APK_CONF}
|
||||
local line
|
||||
while read -r line; do
|
||||
if [[ -n "$line" ]]; then
|
||||
grep -Fxq "$line" /etc/apk/arch || echo "$line" >> /etc/apk/arch
|
||||
fi
|
||||
done < ${IS_ROOT}/etc/arch
|
||||
sync /etc/apk/arch
|
||||
if [[ ! -s /etc/apk/keys/istore.pem && ! -s /etc/apk/keys/istore-tmp.pem ]]; then
|
||||
fcurl --no-progress-meter -o ${IS_ROOT}/etc/istore.pem "${FEEDS_SERVER}/istore-apk.pem" && \
|
||||
cp -a ${IS_ROOT}/etc/istore.pem /etc/apk/keys/istore-tmp.pem || \
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
fcurl --no-progress-meter -o ${OPKG_CONF_DIR}/meta.conf "${FEEDS_SERVER}/all/meta.conf" && \
|
||||
fcurl --no-progress-meter -o ${OPKG_CONF_DIR}/all.conf "${FEEDS_SERVER}/all/isfeeds.conf" && \
|
||||
fcurl --no-progress-meter -o ${OPKG_CONF_DIR}/arch.conf "${FEEDS_SERVER}/${ARCH}/isfeeds.conf" || \
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Update feeds index"
|
||||
if $USE_APK; then
|
||||
apk_wrap update
|
||||
else
|
||||
opkg -f ${IS_ROOT}/etc/opkg_o.conf --offline-root ${IS_ROOT} update
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
update_if_outdate() {
|
||||
local idle_t=$((`date '+%s'` - `date -r ${IS_ROOT}/.last_force_ts '+%s' 2>/dev/null || echo '0'`))
|
||||
[ $idle_t -gt ${1:-120} ] || return 2
|
||||
update || return 1
|
||||
touch ${IS_ROOT}/.last_force_ts
|
||||
return 0
|
||||
}
|
||||
|
||||
get_online_version() {
|
||||
local index="$1"
|
||||
local pkg="$2"
|
||||
if $USE_APK; then
|
||||
apk --cache-dir $LISTS_DIR --cache-max-age 0 --repositories-file /dev/null --repository "$index" update >/dev/null 2>&1
|
||||
apk --cache-dir $LISTS_DIR --cache-max-age 0 --repositories-file /dev/null --repository "$index" query --available --fields version "$pkg" 2>/dev/null | grep -Fm1 'Version: ' | sed 's/^Version: //'
|
||||
else
|
||||
curl --connect-timeout 2 --max-time 5 -s "$index" | gunzip | grep -FA10 "Package: $pkg" | grep -Fm1 'Version: ' | sed 's/^Version: //'
|
||||
fi
|
||||
}
|
||||
|
||||
get_local_version() {
|
||||
local pkg="$1"
|
||||
if $USE_APK; then
|
||||
apk query --installed --fields version "$pkg" 2>/dev/null | grep -Fm1 'Version: ' | sed 's/^Version: //'
|
||||
else
|
||||
grep -Fm1 'Version: ' /usr/lib/opkg/info/$pkg.control 2>/dev/null | sed 's/^Version: //'
|
||||
fi
|
||||
}
|
||||
|
||||
check_self_upgrade() {
|
||||
local newest=`get_online_version "$ISTORE_INDEX" "$ISTORE_PKG"`
|
||||
local current=`get_local_version "$ISTORE_PKG"`
|
||||
if [ "v$newest" = "v" -o "v$current" = "v" ]; then
|
||||
echo "Check version failed!" >&2
|
||||
exit 255
|
||||
fi
|
||||
if [ "$newest" != "$current" ]; then
|
||||
echo "$newest"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
do_self_upgrade_0() {
|
||||
simple_apk_opkg upgrade ${ISTORE_DEP_PKGS} && simple_apk_opkg upgrade ${ISTORE_PKG}
|
||||
}
|
||||
|
||||
do_self_upgrade() {
|
||||
check_mtime || return 1
|
||||
local newest=`get_online_version "$ISTORE_INDEX" "$ISTORE_PKG"`
|
||||
local current=`get_local_version "$ISTORE_PKG"`
|
||||
if [ "v$newest" = "v" -o "v$current" = "v" ]; then
|
||||
echo "Check version failed!" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$newest" = "$current" ]; then
|
||||
echo "Already the latest version!" >&2
|
||||
return 1
|
||||
fi
|
||||
if $USE_APK || opkg_wrap info ${ISTORE_PKG} | grep -qFm1 "Version: $newest"; then
|
||||
do_self_upgrade_0 && return 0
|
||||
update_if_outdate || return 1
|
||||
do_self_upgrade_0
|
||||
else
|
||||
update_if_outdate || return 1
|
||||
do_self_upgrade_0
|
||||
fi
|
||||
}
|
||||
|
||||
check_mtime() {
|
||||
local file
|
||||
if $USE_APK; then
|
||||
file=${APK_CONF}
|
||||
else
|
||||
file=${OPKG_CONF_DIR}/arch.conf
|
||||
fi
|
||||
find "$file" -mtime -1 2>/dev/null | grep -q . || update
|
||||
}
|
||||
|
||||
wrapped_in_update() {
|
||||
check_mtime || return 1
|
||||
eval "$@" && return 0
|
||||
update_if_outdate || return 1
|
||||
eval "$@"
|
||||
}
|
||||
|
||||
refresh_installed() {
|
||||
local pkg
|
||||
for pkg in $@; do
|
||||
[[ $pkg == app-meta-* ]] || continue
|
||||
pkg="$META_DIR/meta/${pkg#app-meta-}.json"
|
||||
[[ -f "$pkg" ]] && touch "$pkg"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
step_upgrade() {
|
||||
local pkg
|
||||
local pkgs=""
|
||||
local metapkg=""
|
||||
for pkg in $@; do
|
||||
if [[ $pkg == app-meta-* ]]; then
|
||||
metapkg="$metapkg $pkg"
|
||||
else
|
||||
pkgs="$pkgs $pkg"
|
||||
fi
|
||||
done
|
||||
if [ -n "$pkgs" ]; then
|
||||
do_upgrade_in_mirrors $pkgs || return 1
|
||||
fi
|
||||
if [ -n "$metapkg" ]; then
|
||||
do_upgrade_in_mirrors $metapkg || return 1
|
||||
refresh_installed $metapkg
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
new_upgrade() {
|
||||
check_mtime || return 1
|
||||
local metapkg=`echo "$@" | sed 's/ /\n/g' | grep -F app-meta-`
|
||||
if [[ -z "$metapkg" ]] || [[ -z "$(get_local_version $metapkg)" ]]; then
|
||||
true
|
||||
else
|
||||
update_if_outdate
|
||||
fi
|
||||
wrapped_in_update step_upgrade "$@"
|
||||
}
|
||||
|
||||
remove() {
|
||||
if $USE_APK; then
|
||||
apk_wrap del -r "$@"
|
||||
else
|
||||
opkg_wrap --autoremove --force-removal-of-dependent-packages remove "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
autoconf_to_env() {
|
||||
local autoconf path enable
|
||||
eval "local autoconf=$ISTORE_AUTOCONF"
|
||||
export -n ISTORE_AUTOCONF
|
||||
export -n ISTORE_DONT_START
|
||||
export -n ISTORE_CONF_DIR
|
||||
export -n ISTORE_CACHE_DIR
|
||||
export -n ISTORE_PUBLIC_DIR
|
||||
export -n ISTORE_DL_DIR
|
||||
|
||||
ISTORE_AUTOCONF=$autoconf
|
||||
|
||||
if [ -n "$path" ]; then
|
||||
export ISTORE_CONF_DIR="$path/Configs"
|
||||
export ISTORE_CACHE_DIR="$path/Caches"
|
||||
export ISTORE_PUBLIC_DIR="$path/Public"
|
||||
export ISTORE_DL_DIR="$ISTORE_PUBLIC_DIR/Downloads"
|
||||
fi
|
||||
[ "$enable" = 0 ] && export ISTORE_DONT_START="1"
|
||||
}
|
||||
|
||||
try_autoconf() {
|
||||
[ -n "$ISTORE_AUTOCONF" ] || return 0
|
||||
autoconf_to_env
|
||||
[ -n "$ISTORE_AUTOCONF" ] || return 1
|
||||
echo "Auto configure $ISTORE_AUTOCONF"
|
||||
PATH="$CLEANPATH" /usr/libexec/istorea/${ISTORE_AUTOCONF}.sh
|
||||
}
|
||||
|
||||
|
||||
try_upgrade_depends() {
|
||||
local pkg="$1"
|
||||
if [[ $pkg == app-meta-* ]]; then
|
||||
local deps
|
||||
if $USE_APK; then
|
||||
deps=$(apk --repositories-file /dev/null info -R "$pkg" | tail +2 | grep -vFw libc | xargs echo)
|
||||
else
|
||||
deps=$(grep '^Depends: ' "/usr/lib/opkg/info/$pkg.control" | busybox sed -e 's/^Depends: //' -e 's/,/\n/g' -e 's/ //g' | grep -vFw libc | xargs echo)
|
||||
fi
|
||||
[ -z "$deps" ] || do_install_in_mirrors $deps
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
if $USE_APK; then
|
||||
CMD_INSTALLED="apk --repositories-file /dev/null info | cut -d' ' -f1 | sort -u"
|
||||
CMD_INSTALL="apk add --allow-untrusted"
|
||||
else
|
||||
CMD_INSTALLED="opkg list-installed | cut -d' ' -f1 | sort -u"
|
||||
CMD_INSTALL="opkg install"
|
||||
fi
|
||||
|
||||
dotrun() {
|
||||
local path="$1"
|
||||
[ -f "$path" ] || { echo "file not found: $path" >&2; return 1; }
|
||||
ls -l "$path"
|
||||
local md5=$(md5sum "$path" 2>/dev/null | cut -d' ' -f1)
|
||||
local ts=$(date '+%s')
|
||||
#local date=$(date '+%Y-%m-%d_%H-%M-%S')
|
||||
echo "MD5: $md5"
|
||||
echo "Save installed pkg list before installing"
|
||||
sh -c "$CMD_INSTALLED" > "/tmp/is-root/tmp/pre_$md5.txt"
|
||||
if echo "$path" | grep -q '\.run$'; then
|
||||
echo "Executing .run file"
|
||||
chmod 0755 "$path" && "$path"
|
||||
else
|
||||
echo "Installing pkg file"
|
||||
$CMD_INSTALL "$path"
|
||||
fi
|
||||
local RET=$?
|
||||
rm -f "$path"
|
||||
if [ -s "/tmp/is-root/tmp/pre_$md5.txt" ]; then
|
||||
echo "Save installed pkg list after installing"
|
||||
sh -c "$CMD_INSTALLED" > "/tmp/is-root/tmp/post_$md5.txt"
|
||||
grep -Fxf "/tmp/is-root/tmp/pre_$md5.txt" -v "/tmp/is-root/tmp/post_$md5.txt" > "/tmp/is-root/tmp/added_$md5.txt"
|
||||
if [ -s "/tmp/is-root/tmp/added_$md5.txt" ]; then
|
||||
echo "The following packages were added:"
|
||||
cat "/tmp/is-root/tmp/added_$md5.txt"
|
||||
mkdir -p /usr/share/istore/run-records
|
||||
path="${path##*/}"
|
||||
path="${path//\\/\\\\}" #\
|
||||
path="${path//\"/\\\"}" #"
|
||||
path="${path//$NEWLINE/\\n}" # \n
|
||||
path="${path//^M/\\r}" # \r
|
||||
echo "{\"id\":\"$ts-$md5\",\"ts\":$ts,\"md5\":\"$md5\",\"file\":\"$path\"}" > /usr/share/istore/run-records/$ts-$md5.txt
|
||||
cat "/tmp/is-root/tmp/added_$md5.txt" >> /usr/share/istore/run-records/$ts-$md5.txt
|
||||
fi
|
||||
fi
|
||||
rm -f "/tmp/is-root/tmp/pre_$md5.txt" "/tmp/is-root/tmp/post_$md5.txt" "/tmp/is-root/tmp/added_$md5.txt"
|
||||
return $RET
|
||||
}
|
||||
|
||||
run_records() {
|
||||
local record
|
||||
local file
|
||||
echo "["
|
||||
for record in /usr/share/istore/run-records/*.txt; do
|
||||
[ -f "$record" ] || continue
|
||||
echo "`head -1 "$record"`,"
|
||||
done | head -c -2
|
||||
echo ""
|
||||
echo "]"
|
||||
}
|
||||
|
||||
|
||||
if $USE_APK; then
|
||||
CMD_REMOVE="apk del"
|
||||
else
|
||||
CMD_REMOVE="opkg --autoremove remove"
|
||||
fi
|
||||
|
||||
unrun() {
|
||||
local id="$1"
|
||||
[ -s "/usr/share/istore/run-records/$id.txt" ] || { echo "record not found: $id" >&2; return 1; }
|
||||
mkdir -p /tmp/is-root/tmp
|
||||
echo "The following packages will be removed:"
|
||||
tail -n +2 "/usr/share/istore/run-records/$id.txt" > "/tmp/is-root/tmp/to_unrun_$id.txt"
|
||||
cat "/tmp/is-root/tmp/to_unrun_$id.txt"
|
||||
local round max_round=6
|
||||
for round in `seq 1 $max_round`; do
|
||||
if [ $round == $max_round ]; then
|
||||
$CMD_REMOVE `cat "/tmp/is-root/tmp/to_unrun_$id.txt"`
|
||||
else
|
||||
$CMD_REMOVE `cat "/tmp/is-root/tmp/to_unrun_$id.txt"` 2>/dev/null && break
|
||||
fi
|
||||
done
|
||||
sh -c "$CMD_INSTALLED" > "/tmp/is-root/tmp/post_unrun_$id.txt"
|
||||
grep -Fxf "/tmp/is-root/tmp/post_unrun_$id.txt" "/tmp/is-root/tmp/to_unrun_$id.txt" > "/tmp/is-root/tmp/remain_unrun_$id.txt"
|
||||
if [ -s "/tmp/is-root/tmp/remain_unrun_$id.txt" ]; then
|
||||
echo "The following packages failed to be removed:"
|
||||
cat "/tmp/is-root/tmp/remain_unrun_$id.txt"
|
||||
else
|
||||
echo "All packages removed successfully."
|
||||
rm -f "/usr/share/istore/run-records/$id.txt"
|
||||
fi
|
||||
rm -f "/tmp/is-root/tmp/to_unrun_$id.txt" "/tmp/is-root/tmp/post_unrun_$id.txt" "/tmp/is-root/tmp/remain_unrun_$id.txt"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
usage() {
|
||||
echo "usage: is-opkg sub-command [arguments...]"
|
||||
echo "where sub-command is one of:"
|
||||
echo " update Update list of available packages"
|
||||
echo " upgrade <pkgs> Upgrade package(s)"
|
||||
echo " install <pkgs> Install package(s)"
|
||||
echo " remove <pkgs|regexp> Remove package(s)"
|
||||
echo " info [pkg|regexp] Display all info for <pkg>"
|
||||
echo " list-upgradable List installed and upgradable packages"
|
||||
echo " check_self_upgrade Check iStore upgrade"
|
||||
echo " do_self_upgrade Upgrade iStore"
|
||||
echo " arch Show libc architecture"
|
||||
echo " opkg sys opkg wrap"
|
||||
echo " dotrun {path} install .run/.ipk/.apk"
|
||||
echo " run_records list .run/.ipk/.apk install records"
|
||||
echo " del_record {id} delete .run/.ipk/.apk install record"
|
||||
echo " unrun {id} Remove installed packages by .run/.ipk/.apk"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ "$action" = "do_self_upgrade" && "$0" != "$TMP_SELF_COPY" ]]; then
|
||||
echo "copy self $0 to $TMP_SELF_COPY when self upgrade"
|
||||
cp -af "$0" "$TMP_SELF_COPY" || exit 1
|
||||
exec "$TMP_SELF_COPY" do_self_upgrade "$@" || exit 1
|
||||
fi
|
||||
|
||||
is_init >/dev/null 2>&1
|
||||
|
||||
CLEANPATH="$PATH"
|
||||
|
||||
case $action in
|
||||
"update"|"install"|"upgrade"|"opkg"|"check_self_upgrade"|"do_self_upgrade"|"dotrun")
|
||||
if [[ "`uci -q get istore.istore.ipv4`" = "1" ]]; then
|
||||
export PATH="/usr/libexec/istore/ipv4-bin:$CLEANPATH"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case $action in
|
||||
"update")
|
||||
update
|
||||
;;
|
||||
"install")
|
||||
check_space
|
||||
wrapped_in_update do_install_in_mirrors "$@" && refresh_installed "$1" && try_upgrade_depends "$1" && try_autoconf
|
||||
;;
|
||||
"autoconf")
|
||||
try_autoconf
|
||||
;;
|
||||
"upgrade")
|
||||
new_upgrade "$@"
|
||||
;;
|
||||
"remove")
|
||||
remove "$@" || remove "$@"
|
||||
;;
|
||||
"info")
|
||||
if $USE_APK; then
|
||||
apk_wrap query "$@"
|
||||
else
|
||||
opkg_wrap info "$@"
|
||||
fi
|
||||
;;
|
||||
"list-upgradable")
|
||||
if $USE_APK; then
|
||||
apk_wrap query --upgradable --summarize package '*'
|
||||
else
|
||||
opkg_wrap list-upgradable
|
||||
fi
|
||||
;;
|
||||
"check_self_upgrade")
|
||||
check_self_upgrade
|
||||
;;
|
||||
"do_self_upgrade")
|
||||
check_space
|
||||
do_self_upgrade
|
||||
;;
|
||||
"arch")
|
||||
echo "$ARCH"
|
||||
;;
|
||||
"opkg")
|
||||
opkg_wrap "$@"
|
||||
;;
|
||||
"dotrun")
|
||||
dotrun "$@"
|
||||
;;
|
||||
"run_records")
|
||||
run_records
|
||||
;;
|
||||
"del_record")
|
||||
rm -f "/usr/share/istore/run-records/$1.txt"
|
||||
;;
|
||||
"unrun")
|
||||
unrun "$1"
|
||||
;;
|
||||
"link_meta")
|
||||
[[ -d "$META_DIR/meta" ]] || mkdir -p "$META_DIR/meta"
|
||||
[ -e /tmp/run/istore-meta ] || ln -sf "$META_DIR" /tmp/run/istore-meta
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,8 @@
|
||||
config istore 'istore'
|
||||
# option hide_docker '0'
|
||||
# option ignore_arch '0'
|
||||
# option last_path '/mnt/nvme'
|
||||
# option channel 'istore'
|
||||
# option super_arch 'x86_64'
|
||||
# option super_arch 'aarch64'
|
||||
# option ipv4 '0'
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2016 OpenWrt.org
|
||||
|
||||
START=45
|
||||
|
||||
boot() {
|
||||
local ARCH=`/bin/is-opkg arch`
|
||||
generate_store_id $ARCH
|
||||
generate_super_arch $ARCH
|
||||
/bin/is-opkg link_meta
|
||||
}
|
||||
|
||||
generate_store_id() {
|
||||
[ -s /etc/.app_store.id ] && return 0
|
||||
local ARCH=$1
|
||||
local iface HASH
|
||||
|
||||
for iface in eth0 br-lan; do
|
||||
if [ -e /sys/class/net/$iface/address ]; then
|
||||
HASH=`md5sum /sys/class/net/$iface/address | cut -d ' ' -f1`
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$HASH" ]; then
|
||||
HASH=`dd if=/dev/urandom bs=512 count=1 2>/dev/null | md5sum | cut -d ' ' -f1`
|
||||
fi
|
||||
|
||||
echo "{\"arch\":\"${ARCH}\", \"uid\":\"${HASH}\"}" > /etc/.app_store.id
|
||||
}
|
||||
|
||||
generate_super_arch() {
|
||||
local ARCH=$1
|
||||
local super_arch
|
||||
case "$ARCH" in
|
||||
arm*)
|
||||
super_arch="arm"
|
||||
;;
|
||||
i386)
|
||||
super_arch="x86"
|
||||
;;
|
||||
x86_64)
|
||||
super_arch="x86_64"
|
||||
;;
|
||||
*)
|
||||
super_arch="${ARCH%%_*}"
|
||||
;;
|
||||
esac
|
||||
local old=`uci -q get istore.istore.super_arch`
|
||||
[ "$old" = "$super_arch" ] && return 0
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set istore.istore.super_arch=$super_arch
|
||||
commit istore
|
||||
EOF
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
/etc/init.d/istore boot
|
||||
|
||||
if [ -z "`uci -q get istore.istore.hide_docker`" ] && ! which docker >/dev/null; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set istore.istore.hide_docker=1
|
||||
commit istore
|
||||
EOF
|
||||
fi
|
||||
|
||||
# remove tmp keys that used for self-installation, which is not needed after installation
|
||||
rm -f /etc/apk/keys/istore-tmp.pem
|
||||
|
||||
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
#!/bin/sh
|
||||
#set -x
|
||||
#IS_DEBUG=1
|
||||
|
||||
IS_ROOT=/tmp/is-backup
|
||||
APP_LIST_FILE=/etc/istore/app.list
|
||||
BACKUP_CONFIG_FILE=/etc/config/istore
|
||||
USE_APK=false
|
||||
[[ -s /etc/apk/arch ]] && USE_APK=true
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
|
||||
is_init() {
|
||||
mkdir -p ${IS_ROOT}
|
||||
}
|
||||
|
||||
opkg_list_installed_packages() {
|
||||
local target=$1
|
||||
local dir
|
||||
local OPKG_INFO_DIR
|
||||
case $target in
|
||||
"preinstalled")
|
||||
OPKG_INFO_DIR="/rom/usr/lib/opkg/info"
|
||||
;;
|
||||
"userinstalled")
|
||||
OPKG_INFO_DIR="/overlay/upper/usr/lib/opkg/info /ext_overlay/upper/usr/lib/opkg/info"
|
||||
;;
|
||||
"allinstalled")
|
||||
OPKG_INFO_DIR="/usr/lib/opkg/info"
|
||||
;;
|
||||
*)
|
||||
echo "invalid target"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
for dir in $OPKG_INFO_DIR ; do
|
||||
[ -d "$dir" ] || continue
|
||||
(cd "$dir" && find . -depth -maxdepth 1 -name "*.list" -type f | sed 's#^\./\(.*\)\.list$#\1#g')
|
||||
done
|
||||
}
|
||||
|
||||
ipk_build() {
|
||||
PKG_NAME_TEMP=$1
|
||||
IPK_OUTPUT_DIR=$2
|
||||
|
||||
UCI_BAK_DIR="/etc/istore/uci-defaults_bak/"
|
||||
UCI_DEF_DIR="etc/uci-defaults"
|
||||
local OPKG_INFO_DIR="/usr/lib/opkg/info/"
|
||||
|
||||
[ -n "${PKG_NAME_TEMP}" ] || exit 1
|
||||
#get real pkg name in opkg
|
||||
PKG_NAME_TEMP=`cat ${IS_ROOT}/all_installed_package.list | sort -u | grep "^${PKG_NAME_TEMP}" | head -n 1`
|
||||
[ -n "${PKG_NAME_TEMP}" ] || exit 1
|
||||
|
||||
PKG_NAME=`cat ${OPKG_INFO_DIR}${PKG_NAME_TEMP}.control | grep "^Package: " | cut -d ' ' -f2`
|
||||
PKG_VER=`cat ${OPKG_INFO_DIR}${PKG_NAME}.control | grep "^Version: " | cut -d ' ' -f2`
|
||||
PKG_ARCH=`cat ${OPKG_INFO_DIR}${PKG_NAME}.control | grep "^Architecture: " | cut -d ' ' -f2`
|
||||
IPK_FILE_NAME="${PKG_NAME}_${PKG_VER}_${PKG_ARCH}"
|
||||
|
||||
rm -rf ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
mkdir -p ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
|
||||
#(1)make CONTROL dir; (2)copy control file to dir
|
||||
cd ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
mkdir -p CONTROL
|
||||
for control_file in `ls ${OPKG_INFO_DIR}${PKG_NAME}.* | grep -v ".list$"`; do
|
||||
file=${control_file##*/}
|
||||
suffix=${file##*.}
|
||||
cp ${control_file} CONTROL/${suffix}
|
||||
done
|
||||
|
||||
#(1)make DATA depend dir; (2)copy uci-defaults_bak file to dir; (3)copy other file to dir
|
||||
for pkgfile in `cat ${OPKG_INFO_DIR}${PKG_NAME}.list | cut -b 2-`; do
|
||||
file=${pkgfile##*/}
|
||||
path=${pkgfile%/*}
|
||||
mkdir -p ${path}
|
||||
if [ `echo "${path}" | grep "^${UCI_DEF_DIR}"` ]; then
|
||||
cp "${UCI_BAK_DIR}${file}" "${pkgfile}"
|
||||
else
|
||||
cp "/${pkgfile}" "${pkgfile}"
|
||||
fi
|
||||
done
|
||||
|
||||
#call ipkg-build script to build ipk
|
||||
/usr/libexec/istore/ipkg-build ${IS_ROOT}/${IPK_FILE_NAME} ${IPK_OUTPUT_DIR}
|
||||
echo "${IPK_FILE_NAME}.ipk" >> ${IPK_OUTPUT_DIR}/appdepipk.list
|
||||
|
||||
[ -n "${IS_DEBUG}" ] || rm -rf ${IS_ROOT}/${IPK_FILE_NAME}
|
||||
}
|
||||
|
||||
# if arg is NULL, use light backup, otherwise use local backup
|
||||
backup() {
|
||||
if [ -n "$1" ]; then
|
||||
if $USE_APK; then
|
||||
echo "does not support apk package manager" >&2
|
||||
exit 1
|
||||
fi
|
||||
BACKUP_PATH=$1
|
||||
fi
|
||||
|
||||
if $USE_APK; then
|
||||
( cd /lib/apk/packages && ls *.list ) | grep '^app-meta-' | sed 's/.list$//' | sort -u > ${IS_ROOT}/istore_installed_package.list
|
||||
else
|
||||
#write user installed package list to file
|
||||
opkg_list_installed_packages "userinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/user_installed_package.list
|
||||
#write installed package list by istore feed to file
|
||||
cat ${IS_ROOT}/user_installed_package.list | \
|
||||
grep '^app-meta-' > ${IS_ROOT}/istore_installed_package.list
|
||||
fi
|
||||
|
||||
#if no input backup path, only back app.list
|
||||
mkdir -p /etc/istore
|
||||
cp ${IS_ROOT}/istore_installed_package.list ${APP_LIST_FILE}
|
||||
echo "backup installed package list to ${APP_LIST_FILE}"
|
||||
|
||||
if [ ! -n "${BACKUP_PATH}" ]; then
|
||||
echo "backup success"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d "${BACKUP_PATH}" ] && ! mkdir -p "${BACKUP_PATH}" ; then
|
||||
echo "invalid backup path, can not backup ipk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#write all installed package list to file
|
||||
opkg_list_installed_packages "allinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/all_installed_package.list
|
||||
|
||||
#write system pre installed package list to file
|
||||
opkg_list_installed_packages "preinstalled" 2>/dev/null | sort -u > ${IS_ROOT}/pre_installed_package.list
|
||||
|
||||
#write installed packages and depends list by istore feed to file by depend sequence
|
||||
appdep_list=""
|
||||
temp_list=`cat ${IS_ROOT}/istore_installed_package.list | sed 's/^/\t/'`
|
||||
while [ -n "${temp_list}" ]
|
||||
do
|
||||
#get real pkg name
|
||||
for PKG_NAME_TEMP in ${temp_list}; do
|
||||
REAL_PKG_NAME=`cat ${IS_ROOT}/all_installed_package.list | sort -u | grep "^${PKG_NAME_TEMP}" | head -n 1`
|
||||
if [ "${REAL_PKG_NAME}" != "${PKG_NAME_TEMP}" ]; then
|
||||
temp_list=`echo "${temp_list}" | sed 's/^\t'"${PKG_NAME_TEMP}"'$/\t'"${REAL_PKG_NAME}"'/'`
|
||||
fi
|
||||
done
|
||||
|
||||
appdep_list=`echo -e "${temp_list}\n${appdep_list}"`
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "temp_list:\n""${temp_list}"
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "appdep_list:\n""${appdep_list}"
|
||||
|
||||
temp_list=`echo "${temp_list}" | xargs opkg depends | grep -v "depends on:" | grep -v " (>= " | grep -v " (= " | sort -u`
|
||||
done
|
||||
|
||||
appdep_list_all=`echo "${appdep_list}" | cut -f2 | grep -v "^$" | awk '!seen[$0]++'`
|
||||
[ -n "${IS_DEBUG}" ] && echo -e "appdep_list_all:\n""${appdep_list_all}"
|
||||
echo "${appdep_list_all}" > ${IS_ROOT}/appdep.list
|
||||
|
||||
#3.rebuild all istore installed package to ipk and backup to userdata partation
|
||||
|
||||
# 4. create dir
|
||||
date=$(date +%Y-%m%d-%H%M)
|
||||
if [ ! -d "$BACKUP_PATH/backup_istore_$date" ];then
|
||||
mkdir $BACKUP_PATH/backup_istore_$date
|
||||
fi
|
||||
cp ${IS_ROOT}/istore_installed_package.list $BACKUP_PATH/backup_istore_$date/app.list
|
||||
cp ${IS_ROOT}/appdep.list $BACKUP_PATH/backup_istore_$date/appdep.list
|
||||
|
||||
#only backup non pre installed ipk
|
||||
cp ${IS_ROOT}/appdep.list ${IS_ROOT}/appdep_strip.list
|
||||
for pre_installed_pkg in `cat ${IS_ROOT}/appdep.list ${IS_ROOT}/pre_installed_package.list | sort -n | uniq -d`; do
|
||||
sed -i '/^'"$pre_installed_pkg"'$/d' ${IS_ROOT}/appdep_strip.list
|
||||
done
|
||||
|
||||
rm -f $BACKUP_PATH/backup_istore_$date/appdepipk.list
|
||||
echo "build ipk"
|
||||
for pkg_name in `cat ${IS_ROOT}/appdep_strip.list`; do
|
||||
ipk_build ${pkg_name} $BACKUP_PATH/backup_istore_$date
|
||||
done
|
||||
|
||||
# 5. create tar.gz file,and remove dir
|
||||
cd $BACKUP_PATH
|
||||
echo "write backup file to $BACKUP_PATH/backup_istore_$date.backup.tar.gz"
|
||||
tar -czf $BACKUP_PATH/backup_istore_$date.backup.tar.gz backup_istore_$date
|
||||
rm -rf $BACKUP_PATH/backup_istore_$date
|
||||
echo "backup success"
|
||||
}
|
||||
|
||||
# if arg is NULL, use light backup, otherwise use local backup
|
||||
restore() {
|
||||
if [ -n "$1" ]; then
|
||||
if $USE_APK; then
|
||||
echo "does not support apk package manager" >&2
|
||||
exit 1
|
||||
fi
|
||||
BACKUP_PATH_FILE=$1
|
||||
else
|
||||
echo "install package by ${APP_LIST_FILE}"
|
||||
is-opkg update
|
||||
for app in `cat ${APP_LIST_FILE}`; do
|
||||
#skip resotre istore self
|
||||
[ "A${app}" == "A""luci-app-store" ] && continue
|
||||
is-opkg install ${app}
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "${BACKUP_PATH_FILE}" ];then
|
||||
echo "invalid backup file, can not restore ipk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#1. Unzip file to dir
|
||||
BACKUP_PATH_FILE_NAME=${BACKUP_PATH_FILE##*/}
|
||||
BACKUP_PATH=/tmp/${BACKUP_PATH_FILE_NAME%.backup.tar.gz*}
|
||||
if [ -d "$BACKUP_PATH" ];then
|
||||
rm -rf $BACKUP_PATH
|
||||
fi
|
||||
mkdir -p $BACKUP_PATH
|
||||
echo "unpack input file..."
|
||||
# fix tar path error
|
||||
tar -zxf ${BACKUP_PATH_FILE} -C /tmp/
|
||||
|
||||
echo "check file"
|
||||
if [ ! -f "${BACKUP_PATH}/appdep.list" ];then
|
||||
echo "no available appdep.list, can not restore ipk"
|
||||
exit 1
|
||||
fi
|
||||
echo "check success"
|
||||
|
||||
#2. install ipk by backup path
|
||||
echo "restore begin"
|
||||
( cd ${BACKUP_PATH}; opkg install `cat ${BACKUP_PATH}/appdepipk.list` )
|
||||
|
||||
#3. rm dir
|
||||
rm -rf ${BACKUP_PATH}
|
||||
echo "restore success"
|
||||
}
|
||||
|
||||
get_support_backup_features() {
|
||||
echo "light_backup"
|
||||
#istore custom img mean support local_backup
|
||||
if ! $USE_APK; then
|
||||
echo "local_backup"
|
||||
fi
|
||||
}
|
||||
|
||||
get_backup_app_list_file_path() {
|
||||
echo "${APP_LIST_FILE}"
|
||||
}
|
||||
|
||||
get_backup_app_list() {
|
||||
if [ ! -f "${APP_LIST_FILE}" ];then
|
||||
echo "no app.list, can not get backup app list"
|
||||
exit 1
|
||||
fi
|
||||
cat ${APP_LIST_FILE}
|
||||
}
|
||||
|
||||
get_available_backup_file_list() {
|
||||
local backup_file
|
||||
if [ -n "$1" ]; then
|
||||
for backup_file in `cd $1 && ls backup_istore_*.backup.tar.gz`; do
|
||||
echo "${backup_file}"
|
||||
done
|
||||
else
|
||||
echo "input backup path is null"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "usage: backup sub-command [arguments...]"
|
||||
echo "where sub-command is one of:"
|
||||
echo " backup [dir] Backup all installed package(s) to [directory]"
|
||||
echo " restore [dir] Restore package(s) by [directory]"
|
||||
echo " get_support_backup_features get device support backup features"
|
||||
echo " get_backup_app_list_file_path get light backup app list file path"
|
||||
echo " get_backup_app_list get light backup app list"
|
||||
echo " get_available_backup_file_list get local available backup file list"
|
||||
}
|
||||
|
||||
is_init >/dev/null 2>&1
|
||||
|
||||
case $action in
|
||||
"get_support_backup_features")
|
||||
get_support_backup_features
|
||||
;;
|
||||
"backup")
|
||||
backup "$@"
|
||||
;;
|
||||
"restore")
|
||||
restore "$@"
|
||||
;;
|
||||
"get_backup_app_list_file_path")
|
||||
get_backup_app_list_file_path
|
||||
;;
|
||||
"get_backup_app_list")
|
||||
get_backup_app_list
|
||||
;;
|
||||
"get_available_backup_file_list")
|
||||
get_available_backup_file_list "$@"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
|
||||
handle_part() {
|
||||
case "$MOUNT" in
|
||||
"/overlay")
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
check_dir() {
|
||||
local data_root=$(uci -q get dockerd.globals.data_root)
|
||||
[ -n "$data_root" ] || return 0
|
||||
local block_dev=$(findmnt -T "$data_root" -v -o SOURCE | sed -n 2p)
|
||||
[ -n "$block_dev" ] || return 0
|
||||
[ "overlayfs:/overlay" = "$block_dev" ] && return 1
|
||||
local line=$(block info "$block_dev" 2>/dev/null)
|
||||
[ -n "$line" ] || return 0
|
||||
eval "${line##*: } handle_part ${line%%: *}"
|
||||
}
|
||||
|
||||
migrate_check(){
|
||||
local dest="$1"
|
||||
[ -n "$dest" ] || {
|
||||
echo "dest dir not specified!" >&2
|
||||
return 1
|
||||
}
|
||||
local data_root="$2"
|
||||
[ -n "$data_root" ] || data_root=$(uci -q get dockerd.globals.data_root)
|
||||
[ -n "$data_root" ] || {
|
||||
echo "get docker data_root failed!" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
[ "$data_root" = "/" ] || data_root="${data_root%%/}"
|
||||
[ "$dest" = "/" ] || dest="${dest%%/}"
|
||||
|
||||
[ "$data_root" = "$dest" ] && {
|
||||
echo "dest dir is the same as data_root!" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
[ 1 = "$FORCE" ] && return 0
|
||||
[ -e "$dest" ] || return 0
|
||||
[ -d "$dest" ] || {
|
||||
echo "$dest is existed and it's not a dir, use FORCE=1 to overwrite it" >&2
|
||||
return 2
|
||||
}
|
||||
[ 0 = "$(ls -A "$dest" | head -1 | wc -l)" ] || {
|
||||
echo "$dest is existed and it's not empty, use FORCE=1 to overwrite it" >&2
|
||||
return 2
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
migrate() {
|
||||
local dest="$1"
|
||||
local data_root=$(uci -q get dockerd.globals.data_root)
|
||||
[ -n "$data_root" ] || {
|
||||
echo "get docker data_root failed!" >&2
|
||||
return 1
|
||||
}
|
||||
[ "$data_root" = "/" ] || data_root="${data_root%%/}"
|
||||
[ "$dest" = "/" ] || dest="${dest%%/}"
|
||||
|
||||
FORCE=1 migrate_check "$dest" "$data_root"
|
||||
local check_result=$?
|
||||
[ 0 = $check_result ] || return $check_result
|
||||
|
||||
if [ "$UCI_ONLY" != 1 ]; then
|
||||
rm -rf "$dest"
|
||||
mkdir -p "$dest"
|
||||
echo "Copy $data_root to $dest ..."
|
||||
cp -a "$data_root/." "$dest/" || return 1
|
||||
fi
|
||||
|
||||
echo "Change dockerd data_root to $dest and restart"
|
||||
uci set dockerd.globals.data_root="$dest"
|
||||
uci commit dockerd
|
||||
/etc/init.d/dockerd restart
|
||||
|
||||
echo "Done"
|
||||
}
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
|
||||
usage() {
|
||||
echo "usage: $1 sub-command [arguments...]"
|
||||
echo "where sub-command is one of:"
|
||||
echo " check_dir Check docker data_root is on extrnal disk"
|
||||
echo " migrate_check {target_dir} Check target_dir is valid for migration, return 2 if target_dir existed and not empty"
|
||||
echo " migrate {target_dir} Migrate docker data_root to target_dir"
|
||||
echo " change_dir {target_dir} Migrate docker data_root to target_dir but change dir only (no data copy)"
|
||||
}
|
||||
|
||||
case $action in
|
||||
"check_dir")
|
||||
check_dir
|
||||
;;
|
||||
"migrate")
|
||||
migrate "$@"
|
||||
;;
|
||||
"migrate_check")
|
||||
migrate_check "$@"
|
||||
;;
|
||||
"change_dir")
|
||||
UCI_ONLY=1 migrate "$@"
|
||||
;;
|
||||
*)
|
||||
usage "$0"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
newpath=$(echo ":$PATH:" | sed -e 's#:/usr/libexec/istore/ipv4-bin:#:#g' -e 's/^:*//' -e 's/:*$//')
|
||||
[ -z "$newpath" ] && newpath="/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
export PATH="$newpath"
|
||||
|
||||
exec curl --ipv4 "$@"
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
newpath=$(echo ":$PATH:" | sed -e 's#:/usr/libexec/istore/ipv4-bin:#:#g' -e 's/^:*//' -e 's/:*$//')
|
||||
[ -z "$newpath" ] && newpath="/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
export PATH="$newpath"
|
||||
|
||||
exec wget -4 "$@"
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
newpath=$(echo ":$PATH:" | sed -e 's#:/usr/libexec/istore/mirror-bin:#:#g' -e 's/^:*//' -e 's/:*$//')
|
||||
[ -z "$newpath" ] && newpath="/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
export PATH="$newpath"
|
||||
|
||||
# if url starts with $IS_ORIG_SERVER, replace it with $IS_MIRROR_SERVER
|
||||
if [ -n "$IS_ORIG_SERVER" ] && [ -n "$IS_MIRROR_SERVER" ]; then
|
||||
n=$#
|
||||
while [ "$n" -gt 0 ]; do
|
||||
i="$1"
|
||||
shift
|
||||
case "$i" in
|
||||
"$IS_ORIG_SERVER"/*.apk|\
|
||||
"$IS_ORIG_SERVER"/*.ipk)
|
||||
i="$IS_MIRROR_SERVER/${i#$IS_ORIG_SERVER/}"
|
||||
;;
|
||||
esac
|
||||
set -- "$@" "$i"
|
||||
n=$((n - 1))
|
||||
done
|
||||
fi
|
||||
export -n IS_ORIG_SERVER IS_MIRROR_SERVER
|
||||
|
||||
exec curl "$@"
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
newpath=$(echo ":$PATH:" | sed -e 's#:/usr/libexec/istore/mirror-bin:#:#g' -e 's/^:*//' -e 's/:*$//')
|
||||
[ -z "$newpath" ] && newpath="/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
export PATH="$newpath"
|
||||
|
||||
# if url starts with $IS_ORIG_SERVER, replace it with $IS_MIRROR_SERVER
|
||||
if [ -n "$IS_ORIG_SERVER" ] && [ -n "$IS_MIRROR_SERVER" ]; then
|
||||
n=$#
|
||||
while [ "$n" -gt 0 ]; do
|
||||
i="$1"
|
||||
shift
|
||||
case "$i" in
|
||||
"$IS_ORIG_SERVER"/*.apk|\
|
||||
"$IS_ORIG_SERVER"/*.ipk)
|
||||
i="$IS_MIRROR_SERVER/${i#$IS_ORIG_SERVER/}"
|
||||
;;
|
||||
esac
|
||||
set -- "$@" "$i"
|
||||
n=$((n - 1))
|
||||
done
|
||||
fi
|
||||
export -n IS_ORIG_SERVER IS_MIRROR_SERVER
|
||||
|
||||
exec wget "$@"
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
#!/bin/sh
|
||||
|
||||
TMP_SELF_COPY=/var/run/cloned-overlay-backup
|
||||
|
||||
action=${1}
|
||||
shift
|
||||
|
||||
has_overlay() {
|
||||
[ -d "/overlay/upper" ] || return 1
|
||||
[ "overlay" = "$(/bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }')" ] || return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
has_ext_overlay() {
|
||||
[ -d "/ext_overlay/upper" ] || return 1
|
||||
grep '^overlayfs:/overlay / ' /proc/mounts | grep -Fq 'upperdir=/ext_overlay/upper' || return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
backup() {
|
||||
if ! has_overlay; then
|
||||
echo "only supports squashfs firmware"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$1" ]; then
|
||||
echo "input backup path is null"
|
||||
exit 1
|
||||
fi
|
||||
local BACKUP_PATH="$1"
|
||||
|
||||
if echo "$BACKUP_PATH" | grep -q -e '^/overlay/upper' -e '^/ext_overlay/upper' ; then
|
||||
echo "can not backup to /overlay/upper, /ext_overlay/upper"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${BACKUP_PATH}" ] && ! mkdir -p "${BACKUP_PATH}" ; then
|
||||
echo "backup path does not exist and can not be create"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local realpath="$(cd "${BACKUP_PATH}"; pwd -P)"
|
||||
if [ -z "$realpath" ]; then
|
||||
echo "cannot get absolute path of ${BACKUP_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local mountpoint=$(findmnt -T $realpath -o TARGET | sed -n 2p)
|
||||
# while read -r; do
|
||||
# if [[ "x$realpath" == "x$REPLY" || "x${realpath#$REPLY/}" != "x$realpath" ]]; then
|
||||
# mountpoint="$REPLY"
|
||||
# break
|
||||
# fi
|
||||
# done < <(
|
||||
# cat /proc/mounts | grep -v '^overlay ' | awk 'NR>1 {print $2}' | grep -v '^/$' | \
|
||||
# sort -u | \
|
||||
# while read -r; do printf "%b\n" "$REPLY" ; done | \
|
||||
# awk '{print length, $0}' | sort -nr | cut -d' ' -f2-
|
||||
# )
|
||||
|
||||
if [ "/" = "$mountpoint" ]; then
|
||||
echo "can not backup to /"
|
||||
exit 1
|
||||
else
|
||||
echo "found mount point $mountpoint"
|
||||
fi
|
||||
|
||||
local filename_suffix=
|
||||
local tar_extra_args=
|
||||
if has_ext_overlay; then
|
||||
tar_extra_args="$tar_extra_args ext_overlay/upper"
|
||||
filename_suffix="${filename_suffix}.s"
|
||||
fi
|
||||
|
||||
local hostname=$(cat /proc/sys/kernel/hostname)
|
||||
local fwver=$(. /etc/openwrt_release; echo $DISTRIB_ID-$DISTRIB_RELEASE)
|
||||
|
||||
local date=$(date +%Y-%m%d-%H%M)
|
||||
local backup_name="backup_overlay_${hostname}_${fwver}_${date}${filename_suffix}.overlay.tar.gz"
|
||||
local backup_full_path="$BACKUP_PATH/$backup_name"
|
||||
echo "writing backup to $backup_full_path"
|
||||
if tar -C / -cz overlay/upper $tar_extra_args > "$backup_full_path" ; then
|
||||
sync "$BACKUP_PATH"
|
||||
echo "backup success"
|
||||
return 0
|
||||
else
|
||||
rm -f "$backup_full_path"
|
||||
echo "backup failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
patch_sandbox_device() {
|
||||
local overlay="$1"
|
||||
local ucidir="$overlay/upper/etc/config"
|
||||
local uci_section=$(uci -c "$ucidir" -q show fstab | grep '^fstab\.@mount\[[0-9]*\]\.target='"'/overlay'\$" | head -1 | grep -o '^fstab\.@mount\[[0-9]*\]')
|
||||
if [ -n "$uci_section" ]; then
|
||||
if [ "x1" = "x$(uci -c "$ucidir" get "$uci_section.enabled")" ]; then
|
||||
uci -c "$ucidir" -q delete "$uci_section.uuid"
|
||||
uci -c "$ucidir" -q delete "$uci_section.label"
|
||||
uci -c "$ucidir" -q delete "$uci_section.device"
|
||||
if [ -n "$SANDBOX_UUID" ]; then
|
||||
uci -c "$ucidir" set "$uci_section.uuid=$SANDBOX_UUID"
|
||||
elif [ -n "$SANDBOX_LABEL" ]; then
|
||||
uci -c "$ucidir" set "$uci_section.label=$SANDBOX_LABEL"
|
||||
else
|
||||
uci -c "$ucidir" set "$uci_section.device=$SANDBOX_DEVICE"
|
||||
fi
|
||||
uci -c "$ucidir" commit fstab
|
||||
echo "found and patched $overlay"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
restore() {
|
||||
if ! has_overlay; then
|
||||
echo "only supports squashfs firmware"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$1" ]; then
|
||||
echo "input backup path is null"
|
||||
exit 1
|
||||
fi
|
||||
local BACKUP_PATH_FILE="$1"
|
||||
|
||||
if [ ! -f "${BACKUP_PATH_FILE}" ]; then
|
||||
echo "invalid backup file, can not restore"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# prevent uci cache
|
||||
rm -rf /var/run/uci
|
||||
|
||||
SANDBOX_UUID=
|
||||
SANDBOX_LABEL=
|
||||
SANDBOX_DEVICE=
|
||||
local tar_extra_args=overlay/upper
|
||||
if has_ext_overlay; then
|
||||
tar_extra_args=
|
||||
if echo "${BACKUP_PATH_FILE}" | grep -q '\.s\.overlay\.tar\.gz$' ; then
|
||||
local uuid label device line
|
||||
local uci_section=$(uci -c /overlay/upper/etc/config show fstab | grep '^fstab\.@mount\[[0-9]*\]\.target='"'/overlay'\$" | head -1 | grep -o '^fstab\.@mount\[[0-9]*\]')
|
||||
if [ -z "$uci_section" ]; then
|
||||
echo "failed to find sandbox config, there is debug info:"
|
||||
uci -c /overlay/upper/etc/config show fstab | grep '^fstab\.[^.]*\.target='"'/overlay'\$"
|
||||
exit 1
|
||||
fi
|
||||
while read line; do
|
||||
export -n "$line"
|
||||
done <<EOF
|
||||
$(uci -c /overlay/upper/etc/config show "$uci_section" | sed -e '/^fstab\.[^\.]*=/d' -e 's/^fstab\.[^\.]*\.//g' | grep -e '^uuid=' -e '^label=' -e '^device=' | sed "s/'//g")
|
||||
EOF
|
||||
SANDBOX_UUID=$uuid
|
||||
SANDBOX_LABEL=$label
|
||||
SANDBOX_DEVICE=$device
|
||||
fi
|
||||
fi
|
||||
|
||||
sync /
|
||||
echo "restoring from ${BACKUP_PATH_FILE}"
|
||||
if tar -C / -xz $tar_extra_args < "${BACKUP_PATH_FILE}" ; then
|
||||
if [ -n "$SANDBOX_UUID" -o -n "$SANDBOX_LABEL" -o -n "$SANDBOX_DEVICE" ]; then
|
||||
echo "patch sandbox device ${SANDBOX_UUID}${SANDBOX_LABEL}${SANDBOX_DEVICE}"
|
||||
patch_sandbox_device /overlay && patch_sandbox_device /ext_overlay
|
||||
fi
|
||||
sync /overlay /ext_overlay
|
||||
echo "restore success"
|
||||
echo "schedule to restart after 5 seconds!"
|
||||
/etc/init.d/tasks task_add reboot 'reboot -d 5'
|
||||
return 0
|
||||
else
|
||||
echo "restore failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
supports_overlay_backup() {
|
||||
has_overlay || return 1
|
||||
echo "overlay"
|
||||
has_ext_overlay && echo "ext_overlay"
|
||||
return 0
|
||||
}
|
||||
|
||||
filter_backups() {
|
||||
if has_ext_overlay; then
|
||||
cat
|
||||
else
|
||||
# do not support restoring sandbox backup on non sandbox env
|
||||
grep -v '\.s\.overlay\.tar\.gz$'
|
||||
fi
|
||||
}
|
||||
|
||||
get_backup_file_list() {
|
||||
if [ -n "$1" ]; then
|
||||
( cd "$1" && ls backup_overlay_*.overlay.tar.gz | filter_backups )
|
||||
return 0
|
||||
else
|
||||
echo "input backup path is null"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "usage: overlay-backup sub-command [arguments...]"
|
||||
echo "where sub-command is one of:"
|
||||
echo " backup [dir] Backup all installed package(s) to [directory]"
|
||||
echo " restore [dir] Restore package(s) by [directory]"
|
||||
echo " supports_overlay_backup check system supports overlay backup"
|
||||
echo " get_backup_file_list [dir] get local available backup file list in [dir]"
|
||||
}
|
||||
|
||||
case $action in
|
||||
"supports_overlay_backup")
|
||||
supports_overlay_backup
|
||||
;;
|
||||
"backup")
|
||||
backup "$@"
|
||||
;;
|
||||
"restore")
|
||||
if [ "$0" = "$TMP_SELF_COPY" ]; then
|
||||
restore "$@"
|
||||
else
|
||||
echo "copy self $0 to $TMP_SELF_COPY when restore"
|
||||
cp -af "$0" "$TMP_SELF_COPY"
|
||||
exec "$TMP_SELF_COPY" restore "$@"
|
||||
fi
|
||||
;;
|
||||
"get_available_backup_file_list")
|
||||
get_backup_file_list "$@"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,27 @@
|
||||
clean:
|
||||
compile:
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_NAME:=luci-lib-dummy
|
||||
INCLUDE_DIR:=./dummy
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
install:
|
||||
[ -n "$(APP_STORE_VERSION)" ]
|
||||
mkdir -p "$(DESTDIR)/www/luci-static" "$(DESTDIR)/etc"
|
||||
cp -a "$(FRONTEND_DIST)/luci-static/istore" "$(DESTDIR)/www/luci-static/"
|
||||
$(SED) 's#\.js"#.js?v=$(APP_STORE_VERSION)"#g' "$(DESTDIR)/www/luci-static/istore/index.js"
|
||||
echo "$(APP_STORE_VERSION)" > "$(DESTDIR)/etc/.app_store.version"
|
||||
ifneq ($(USE_APK),)
|
||||
cp -pR ./root-apk/* "$(DESTDIR)/"
|
||||
else
|
||||
cp -pR ./root-opkg/* "$(DESTDIR)/"
|
||||
mkdir -p "$(DESTDIR)/etc/opkg/keys"
|
||||
cp -a ./key-build.pub $(DESTDIR)/etc/opkg/keys/`$(STAGING_DIR_HOST)/bin/usign -F -p ./key-build.pub`
|
||||
endif
|
||||
mkdir -p "$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n"
|
||||
$(foreach lang,$(LUCI_LANGUAGES),$(foreach po,$(wildcard ${CURDIR}/po/$(lang)/*.po), \
|
||||
po2lmo $(po) \
|
||||
$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n/$(basename $(notdir $(po))).$(lang).lmo;))
|
||||
@@ -0,0 +1,2 @@
|
||||
define BuildPackage
|
||||
endef
|
||||
@@ -0,0 +1,2 @@
|
||||
untrusted comment: istore key
|
||||
RWSlbxYnTG1Ia0BvB+xd7YdP7QDQACljfpve7sx9KYq94QgIqtlljuME
|
||||
@@ -0,0 +1,11 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "en"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr ""
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr ""
|
||||
@@ -0,0 +1,11 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "zh-cn"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr "iStore"
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr "此软件包已损坏!请重新安装或卸载它。"
|
||||
@@ -0,0 +1,11 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "istore_vue_lang"
|
||||
msgstr "zh-cn"
|
||||
|
||||
msgid "iStore"
|
||||
msgstr "iStore"
|
||||
|
||||
msgid "This package is broken! Please reinstall or uninstall it."
|
||||
msgstr "此軟體包已損壞!請重新安裝或卸載它。"
|
||||
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEybK5eaXsrK06Thc1dbA3FC45Tlp8
|
||||
8X5Z831vU6JggiV6tJiwI/B05IsdklTaZE8SYh0XCHcnXSjzRMLtarBisg==
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
https://istore.istoreos.com/repo-apk/all/compat/packages.adb
|
||||
@@ -0,0 +1 @@
|
||||
src/gz istore_compat https://istore.istoreos.com/repo/all/compat
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
#!/bin/sh
|
||||
|
||||
# ipkg-build -- construct a .ipk from a directory
|
||||
# Carl Worth <cworth@east.isi.edu>
|
||||
# based on a script by Steve Redler IV, steve@sr-tech.com 5-21-2001
|
||||
# 2003-04-25 rea@sr.unh.edu
|
||||
# Updated to work on Familiar Pre0.7rc1, with busybox tar.
|
||||
# Note it Requires: binutils-ar (since the busybox ar can't create)
|
||||
# For UID debugging it needs a better "find".
|
||||
set -e
|
||||
|
||||
version=1.0
|
||||
FIND="$(command -v find)"
|
||||
FIND="${FIND:-$(command -v gfind)}"
|
||||
TAR="${TAR:-$(command -v tar)}"
|
||||
GZIP="$(command -v gzip)"
|
||||
|
||||
# try to use fixed source epoch
|
||||
if [ -n "$PKG_SOURCE_DATE_EPOCH" ]; then
|
||||
TIMESTAMP=$(date --date="@$PKG_SOURCE_DATE_EPOCH")
|
||||
elif [ -n "$SOURCE_DATE_EPOCH" ]; then
|
||||
TIMESTAMP=$(date --date="@$SOURCE_DATE_EPOCH")
|
||||
else
|
||||
TIMESTAMP=$(date)
|
||||
fi
|
||||
|
||||
ipkg_extract_value() {
|
||||
sed -e "s/^[^:]*:[[:space:]]*//"
|
||||
}
|
||||
|
||||
required_field() {
|
||||
field=$1
|
||||
|
||||
grep "^$field:" < $CONTROL/control | ipkg_extract_value
|
||||
}
|
||||
|
||||
pkg_appears_sane() {
|
||||
local pkg_dir=$1
|
||||
|
||||
local owd=$PWD
|
||||
cd $pkg_dir
|
||||
|
||||
PKG_ERROR=0
|
||||
pkg=`required_field Package`
|
||||
version=`required_field Version | sed 's/Version://; s/^.://g;'`
|
||||
arch=`required_field Architecture`
|
||||
|
||||
if echo $pkg | grep '[^a-zA-Z0-9_.+-]'; then
|
||||
echo "*** Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])" >&2
|
||||
PKG_ERROR=1;
|
||||
fi
|
||||
|
||||
if [ -f $CONTROL/conffiles ]; then
|
||||
rm -f $CONTROL/conffiles.resolved
|
||||
|
||||
for cf in `$FIND $(sed -e "s!^/!$pkg_dir/!" $CONTROL/conffiles) -type f`; do
|
||||
echo "${cf#$pkg_dir}" >> $CONTROL/conffiles.resolved
|
||||
done
|
||||
|
||||
rm $CONTROL/conffiles
|
||||
if [ -f $CONTROL/conffiles.resolved ]; then
|
||||
mv $CONTROL/conffiles.resolved $CONTROL/conffiles
|
||||
chmod 0644 $CONTROL/conffiles
|
||||
fi
|
||||
fi
|
||||
|
||||
cd $owd
|
||||
return $PKG_ERROR
|
||||
}
|
||||
|
||||
resolve_file_mode_id() {
|
||||
local var=$1 type=$2 name=$3 id
|
||||
|
||||
case "$name" in
|
||||
root)
|
||||
id=0
|
||||
;;
|
||||
*[!0-9]*)
|
||||
id=$(sed -ne "s#^$type $name \\([0-9]\\+\\)\\b.*\$#\\1#p" "$TOPDIR/tmp/.packageusergroup" 2>/dev/null)
|
||||
;;
|
||||
*)
|
||||
id=$name
|
||||
;;
|
||||
esac
|
||||
|
||||
export "$var=$id"
|
||||
|
||||
[ -n "$id" ]
|
||||
}
|
||||
|
||||
###
|
||||
# ipkg-build "main"
|
||||
###
|
||||
file_modes=""
|
||||
usage="Usage: $0 [-v] [-h] [-m] <pkg_directory> [<destination_directory>]"
|
||||
while getopts "hvm:" opt; do
|
||||
case $opt in
|
||||
v ) echo $version
|
||||
exit 0
|
||||
;;
|
||||
h ) echo $usage >&2 ;;
|
||||
m ) file_modes=$OPTARG ;;
|
||||
\? ) echo $usage >&2
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
# continue on to process additional arguments
|
||||
|
||||
case $# in
|
||||
1)
|
||||
dest_dir=$PWD
|
||||
;;
|
||||
2)
|
||||
dest_dir=$2
|
||||
if [ "$dest_dir" = "." -o "$dest_dir" = "./" ] ; then
|
||||
dest_dir=$PWD
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
pkg_dir=$1
|
||||
|
||||
if [ ! -d $pkg_dir ]; then
|
||||
echo "*** Error: Directory $pkg_dir does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# CONTROL is second so that it takes precedence
|
||||
CONTROL=
|
||||
[ -d $pkg_dir/CONTROL ] && CONTROL=CONTROL
|
||||
if [ -z "$CONTROL" ]; then
|
||||
echo "*** Error: Directory $pkg_dir has no CONTROL subdirectory." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! pkg_appears_sane $pkg_dir; then
|
||||
echo >&2
|
||||
echo "ipkg-build: Please fix the above errors and try again." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_dir=$dest_dir/IPKG_BUILD.$$
|
||||
mkdir $tmp_dir
|
||||
|
||||
echo $CONTROL > $tmp_dir/tarX
|
||||
cd $pkg_dir
|
||||
for file_mode in $file_modes; do
|
||||
case $file_mode in
|
||||
/*:*:*:*)
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: file modes must use absolute path and contain user:group:mode"
|
||||
echo "$file_mode"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mode=${file_mode##*:}; path=${file_mode%:*}
|
||||
group=${path##*:}; path=${path%:*}
|
||||
user=${path##*:}; path=${path%:*}
|
||||
|
||||
if ! resolve_file_mode_id uid user "$user"; then
|
||||
echo "ERROR: unable to resolve uid of $user" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! resolve_file_mode_id gid group "$group"; then
|
||||
echo "ERROR: unable to resolve gid of $group" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chown "$uid:$gid" "$pkg_dir/$path"
|
||||
chmod "$mode" "$pkg_dir/$path"
|
||||
done
|
||||
$TAR -X $tmp_dir/tarX --format=gnu --sort=name -cpf - --mtime="$TIMESTAMP" . | $GZIP -n - > $tmp_dir/data.tar.gz
|
||||
|
||||
installed_size=`ls -ln $tmp_dir/data.tar.gz | awk 'NR==1 {print $5}'`
|
||||
sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \
|
||||
$pkg_dir/$CONTROL/control
|
||||
|
||||
( cd $pkg_dir/$CONTROL && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" . | $GZIP -n - > $tmp_dir/control.tar.gz )
|
||||
rm $tmp_dir/tarX
|
||||
|
||||
echo "2.0" > $tmp_dir/debian-binary
|
||||
|
||||
pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk
|
||||
rm -f $pkg_file
|
||||
( cd $tmp_dir && $TAR --format=gnu --sort=name -cf - --mtime="$TIMESTAMP" ./debian-binary ./data.tar.gz ./control.tar.gz | $GZIP -n - > $pkg_file )
|
||||
|
||||
rm $tmp_dir/debian-binary $tmp_dir/data.tar.gz $tmp_dir/control.tar.gz
|
||||
rmdir $tmp_dir
|
||||
|
||||
echo "Packaged contents of $pkg_dir into $pkg_file"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
for i in "$@"; do
|
||||
echo "$i" | grep -s -q "/etc/uci-defaults/" \
|
||||
&& mkdir -p /etc/istore/uci-defaults_bak \
|
||||
&& cp -f "$i" /etc/istore/uci-defaults_bak/
|
||||
done
|
||||
/bin/rm "$@"
|
||||
@@ -0,0 +1,513 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
description: Store API V1
|
||||
title: Store API V1
|
||||
version: 3.0.0
|
||||
paths:
|
||||
/cgi-bin/luci/admin/store/token:
|
||||
get:
|
||||
tags:
|
||||
- token
|
||||
summary: 获取csrfToken(用于POST请求)
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreToken"
|
||||
/cgi-bin/luci/admin/store/installed:
|
||||
get:
|
||||
tags:
|
||||
- installed
|
||||
summary: 获取已安装的插件
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreInstalled"
|
||||
/cgi-bin/luci/admin/store/install:
|
||||
post:
|
||||
tags:
|
||||
- install
|
||||
summary: 安装插件。安装过程中使用taskd接口获取日志
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "autoconf"
|
||||
type: string
|
||||
description: "可选参数,表示安装完以后是否自动配置插件"
|
||||
- in: "query"
|
||||
name: "path"
|
||||
type: string
|
||||
description: "可选参数,表示安装完以后是否自动配置插件"
|
||||
- in: "query"
|
||||
name: "enable"
|
||||
type: string
|
||||
description: "可选参数,表示安装完以后是否自动配置插件"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/autoconf:
|
||||
post:
|
||||
tags:
|
||||
- install
|
||||
summary: 自动配置插件
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "path"
|
||||
type: string
|
||||
description: "可选参数"
|
||||
- in: "query"
|
||||
name: "enable"
|
||||
type: string
|
||||
description: "可选参数"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/remove:
|
||||
post:
|
||||
tags:
|
||||
- remove
|
||||
summary: 卸载插件
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/upgrade:
|
||||
post:
|
||||
tags:
|
||||
- upgrade
|
||||
summary: 更新插件
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/upload:
|
||||
post:
|
||||
tags:
|
||||
- upload
|
||||
summary: 上传插件
|
||||
description: "(文件上传表单,支持文件扩展名 .ipk,.run )"
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- in: formData
|
||||
name: file
|
||||
type: file
|
||||
description: The file to upload.
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/update:
|
||||
post:
|
||||
tags:
|
||||
- update
|
||||
summary: 刷新可用软件列表
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/status:
|
||||
get:
|
||||
tags:
|
||||
- status
|
||||
summary: 查询特定软件状态
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreStatus"
|
||||
/cgi-bin/luci/admin/store/log:
|
||||
get:
|
||||
tags:
|
||||
- log
|
||||
summary: 任务日志,已废弃
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/check_self_upgrade:
|
||||
get:
|
||||
tags:
|
||||
- check_self_upgrade
|
||||
summary: 检查iStore自身更新
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreCheckSelfUpgrade"
|
||||
/cgi-bin/luci/admin/store/do_self_upgrade:
|
||||
post:
|
||||
tags:
|
||||
- do_self_upgrade
|
||||
summary: 更新iStore自身
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
/cgi-bin/luci/admin/store/get_block_devices:
|
||||
get:
|
||||
tags:
|
||||
- get_block_devices
|
||||
summary: 枚举块设备
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreGetBlockDevices"
|
||||
/cgi-bin/luci/admin/store/configured:
|
||||
get:
|
||||
tags:
|
||||
- configured
|
||||
summary: 检查插件是否已经配置过
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "uci"
|
||||
type: string
|
||||
required: true
|
||||
description: "要检查的uci配置文件名称"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreConfigured"
|
||||
/cgi-bin/luci/admin/store/entrysh:
|
||||
post:
|
||||
tags:
|
||||
- entrysh
|
||||
summary: 查询插件运行状态,主要为了获取入口信息。
|
||||
description: 调用前应该检查meta数据中flags数组包含entrysh,注意如果是安装插件则检查服务器端的flags,如果是调用已安装插件则检查路由器端的flags。
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "package"
|
||||
type: string
|
||||
description: "包名,例如aria2。支持英文逗号分隔多个包名。如果未提供,则返回所有支持entrysh的包"
|
||||
- in: "query"
|
||||
name: "hostname"
|
||||
type: string
|
||||
required: true
|
||||
description: "主机名,不包含端口。前端应该使用location.hostname获取"
|
||||
- in: "query"
|
||||
name: "update"
|
||||
type: integer
|
||||
description: "如果为1则强制更新缓存"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStoreEntrysh"
|
||||
"400":
|
||||
description: Bad Request。hostname不合法
|
||||
/cgi-bin/luci/admin/store/docker_check_dir:
|
||||
get:
|
||||
tags:
|
||||
- docker_check_dir
|
||||
summary: 检查docker目录是否在系统盘
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseDockerCheckDir"
|
||||
/cgi-bin/luci/admin/store/docker_check_migrate:
|
||||
get:
|
||||
tags:
|
||||
- docker_check_migrate
|
||||
summary: 检查docker迁移目标目录是否有效
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "path"
|
||||
type: string
|
||||
required: true
|
||||
description: "完整目标路径"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseDockerCheckMigrate"
|
||||
/cgi-bin/luci/admin/store/docker_migrate:
|
||||
post:
|
||||
tags:
|
||||
- docker_migrate
|
||||
summary: docker迁移到目标目录,异步
|
||||
description: 当返回code为0的时候,可以使用taskd接口展示日志,跟安装插件时一样
|
||||
parameters:
|
||||
- in: "query"
|
||||
name: "token"
|
||||
type: string
|
||||
required: true
|
||||
- in: "query"
|
||||
name: "path"
|
||||
type: string
|
||||
required: true
|
||||
description: "完整目标路径"
|
||||
- in: "query"
|
||||
name: "overwrite"
|
||||
type: string
|
||||
description: "如果docker_check_migrate返回的result是existed,使用此参数指定解决方案:‘true’表示覆盖目标目录;‘chdir’表示只修改路径不复制文件"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/ResponseStore"
|
||||
|
||||
definitions:
|
||||
ResponseStoreToken:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
StoreInstalledApp:
|
||||
type: object
|
||||
properties:
|
||||
tutorial:
|
||||
type: string
|
||||
description: "教程"
|
||||
arch:
|
||||
type: array
|
||||
description: "适用的架构平台"
|
||||
items:
|
||||
type: string
|
||||
entry:
|
||||
type: string
|
||||
description: "对于的页面地址"
|
||||
author:
|
||||
type: string
|
||||
description: "作者"
|
||||
depends:
|
||||
type: array
|
||||
description: "关联的依赖"
|
||||
items:
|
||||
type: string
|
||||
time:
|
||||
type: integer
|
||||
description: "更新日期"
|
||||
tags:
|
||||
type: array
|
||||
description: "标签"
|
||||
items:
|
||||
type: string
|
||||
description_en:
|
||||
type: string
|
||||
description: "简介,英文"
|
||||
description:
|
||||
type: string
|
||||
description: "简介,英文"
|
||||
title:
|
||||
type: string
|
||||
description: "标题"
|
||||
release:
|
||||
type: integer
|
||||
description: "发布"
|
||||
website:
|
||||
type: string
|
||||
description: "官网"
|
||||
version:
|
||||
type: string
|
||||
description: "版本号"
|
||||
name:
|
||||
type: string
|
||||
description: "名称"
|
||||
ResponseStoreInstalled:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/StoreInstalledApp"
|
||||
ResponseStore:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
stdout:
|
||||
type: string
|
||||
stderr:
|
||||
type: string
|
||||
ResponseStoreStatus:
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: "#/definitions/StoreInstalledApp"
|
||||
properties:
|
||||
installed:
|
||||
type: boolean
|
||||
ResponseStoreCheckSelfUpgrade:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时,msg会显示版本号"
|
||||
msg:
|
||||
type: string
|
||||
description: "内容"
|
||||
GetBlockDevice:
|
||||
type: object
|
||||
properties:
|
||||
dev:
|
||||
type: string
|
||||
uuid:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
mount:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
ResponseStoreGetBlockDevices:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时"
|
||||
msg:
|
||||
type: string
|
||||
description: "内容"
|
||||
data:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: "#/definitions/GetBlockDevice"
|
||||
ResponseStoreConfigured:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时"
|
||||
configured:
|
||||
type: boolean
|
||||
ResponseDockerCheckDir:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时"
|
||||
docker_on_system:
|
||||
type: boolean
|
||||
description: "docker数据在系统盘"
|
||||
ResponseDockerCheckMigrate:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时"
|
||||
result:
|
||||
type: string
|
||||
description: "检查结果。可能值‘good’,‘bad’,‘existed’"
|
||||
error:
|
||||
type: string
|
||||
description: "当result为bad时,此处返回错误日志"
|
||||
StoreEntrysh:
|
||||
type: object
|
||||
description: "状态和入口信息,不同插件可能有些不一样,仅列出常用公共参数"
|
||||
properties:
|
||||
app:
|
||||
type: string
|
||||
description: "插件名称"
|
||||
docker:
|
||||
type: boolean
|
||||
description: "如果是docker插件"
|
||||
running:
|
||||
type: boolean
|
||||
description: "是否运行中"
|
||||
deployed:
|
||||
type: boolean
|
||||
description: "如果是docker插件且未运行,则是否已经部署"
|
||||
web:
|
||||
type: string
|
||||
description: "url"
|
||||
href:
|
||||
type: string
|
||||
description: "web端直接跳转url"
|
||||
|
||||
ResponseStoreEntrysh:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: "为200时"
|
||||
status:
|
||||
description: "处理成功的结果集"
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/StoreEntrysh"
|
||||
errors:
|
||||
description: "处理失败的结果集"
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
description: "失败信息"
|
||||
properties:
|
||||
app:
|
||||
type: string
|
||||
description: "插件名称"
|
||||
code:
|
||||
type: integer
|
||||
description: "404或500"
|
||||
msg:
|
||||
type: string
|
||||
description: "错误信息"
|
||||
|
||||
Reference in new issue
Block a user