├── README.md ├── homebox ├── files │ ├── homebox.config │ ├── homebox.uci-default │ └── homebox.init └── Makefile ├── luci-app-cpufreq ├── root │ └── etc │ │ ├── config │ │ ├── tuning │ │ ├── tuning_boot │ │ ├── tuning_net │ │ └── cpufreq │ │ ├── uci-defaults │ │ ├── 21_tuning │ │ ├── 21_cpufreq │ │ └── 21_tuning_net │ │ └── init.d │ │ ├── tuning │ │ ├── cpufreq │ │ ├── tuning_net │ │ └── await_fstab ├── luasrc │ ├── view │ │ └── cpufreq │ │ │ ├── sb_info.zh-cn.htm │ │ │ ├── sb_guide.zh-cn.htm │ │ │ ├── sb_guide.htm │ │ │ ├── sb_info.htm │ │ │ ├── cpuinfo.htm │ │ │ └── sandbox.htm │ ├── model │ │ └── cbi │ │ │ └── cpufreq │ │ │ ├── samba.lua │ │ │ ├── net.lua │ │ │ ├── kmods.lua │ │ │ ├── ipk.lua │ │ │ ├── main.lua │ │ │ ├── boot.lua │ │ │ └── cmdline.lua │ └── controller │ │ └── admin │ │ └── cpufreq.lua ├── Makefile └── po │ ├── en │ └── cpufreq.po │ ├── templates │ └── cpufreq.pot │ └── zh-cn │ └── cpufreq.po ├── luci-app-homebox ├── luasrc │ ├── view │ │ ├── admin_status │ │ │ └── index │ │ │ │ └── homebox.htm │ │ └── homebox_status.htm │ ├── model │ │ └── cbi │ │ │ └── homebox.lua │ └── controller │ │ └── homebox.lua ├── root │ └── etc │ │ └── uci-defaults │ │ └── 50_luci-homebox ├── Makefile └── po │ └── zh-cn │ └── homebox.po ├── luci-app-mergerfs ├── root │ └── usr │ │ └── share │ │ ├── ucitrack │ │ └── luci-app-mergerfs.json │ │ ├── luci │ │ └── menu.d │ │ │ └── luci-app-mergerfs.json │ │ └── rpcd │ │ └── acl.d │ │ └── luci-app-mergerfs.json ├── Makefile ├── po │ └── zh_Hans │ │ └── mergerfs.po └── htdocs │ └── luci-static │ └── resources │ └── view │ └── mergerfs.js ├── luci-app-fan ├── root │ ├── etc │ │ ├── config │ │ │ └── luci-fan │ │ ├── uci-defaults │ │ │ └── luci-fan │ │ └── init.d │ │ │ └── luci-fan │ └── usr │ │ └── libexec │ │ └── fan-control ├── Makefile ├── luasrc │ ├── view │ │ └── luci-fan.htm │ ├── controller │ │ └── admin │ │ │ └── luci-fan.lua │ └── model │ │ └── cbi │ │ └── luci-fan.lua └── po │ ├── templates │ └── luci-fan.pot │ └── zh-cn │ └── luci-fan.po ├── luci-alias.mk ├── luci-lib-mac-vendor ├── src │ └── Makefile └── Makefile ├── mergerfs ├── files │ ├── mergerfs.config │ ├── mergerfs.fstab │ └── mergerfs.init ├── patches │ ├── 002-fix-install.patch │ ├── 003-fix-build-non-x86-target.patch │ └── 001-fix-lto.patch └── Makefile ├── luci-app-tasks ├── luasrc │ ├── controller │ │ └── tasks-app.lua │ ├── view │ │ └── tasks │ │ │ └── all.htm │ └── model │ │ └── cbi │ │ └── tasks │ │ └── all.lua ├── Makefile └── po │ └── zh-cn │ └── tasks.po ├── ssd1306 ├── test.sh └── Makefile ├── LICENSE ├── nvtop └── Makefile └── duperemove └── Makefile /README.md: -------------------------------------------------------------------------------- 1 | # openwrt-apps 2 | app for openwrt luci 3 | -------------------------------------------------------------------------------- /homebox/files/homebox.config: -------------------------------------------------------------------------------- 1 | config homebox 2 | option 'enabled' '0' 3 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/config/tuning: -------------------------------------------------------------------------------- 1 | config ipk 2 | option mirror 'disable' 3 | -------------------------------------------------------------------------------- /luci-app-homebox/luasrc/view/admin_status/index/homebox.htm: -------------------------------------------------------------------------------- 1 | <%+homebox_status%> 2 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/config/tuning_boot: -------------------------------------------------------------------------------- 1 | config fstab_delay 2 | option enabled '0' 3 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/config/tuning_net: -------------------------------------------------------------------------------- 1 | config hw_acct 2 | option wan_acct '1' 3 | option hw_pppoe '1' -------------------------------------------------------------------------------- /luci-app-homebox/root/etc/uci-defaults/50_luci-homebox: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -f /tmp/luci-indexcache 4 | exit 0 5 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/config/cpufreq: -------------------------------------------------------------------------------- 1 | config cpufreq 2 | # option governor 'ondemand' 3 | # option speed '1000000' 4 | -------------------------------------------------------------------------------- /luci-app-mergerfs/root/usr/share/ucitrack/luci-app-mergerfs.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": "mergerfs", 3 | "init": "mergerfs" 4 | } 5 | -------------------------------------------------------------------------------- /luci-app-fan/root/etc/config/luci-fan: -------------------------------------------------------------------------------- 1 | config luci-fan 2 | option enabled 0 3 | # option on_temp 55 4 | # option off_temp 50 -------------------------------------------------------------------------------- /homebox/files/homebox.uci-default: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | uci -q batch <<-EOF >/dev/null 4 | delete ucitrack.@homebox[-1] 5 | add ucitrack homebox 6 | set ucitrack.@homebox[-1].init=homebox 7 | commit ucitrack 8 | EOF 9 | 10 | exit 0 -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/uci-defaults/21_tuning: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | uci -q batch <<-EOF >/dev/null 4 | delete ucitrack.@tuning[-1] 5 | add ucitrack tuning 6 | set ucitrack.@tuning[-1].init=tuning 7 | commit ucitrack 8 | EOF 9 | 10 | exit 0 -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/sb_info.zh-cn.htm: -------------------------------------------------------------------------------- 1 |

当前处于沙箱环境

2 |

点击“提交”可将变更合并到非沙箱环境,点击“重置”可将沙箱恢复到初始状态

3 |

点击“退出沙箱”可退出沙箱环境

4 |

以上操作都将重启设备

5 |

关机以后移除相关U盘或者移动硬盘能临时退出沙箱环境

6 |

若开发中的软件已经打包进固件并已经刷机,可“重置”沙箱以使用固件中的版本

7 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/uci-defaults/21_cpufreq: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | uci -q batch <<-EOF >/dev/null 4 | delete ucitrack.@cpufreq[-1] 5 | add ucitrack cpufreq 6 | set ucitrack.@cpufreq[-1].init=cpufreq 7 | commit ucitrack 8 | EOF 9 | 10 | exit 0 -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/uci-defaults/21_tuning_net: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | uci -q batch <<-EOF >/dev/null 4 | delete ucitrack.@tuning_net[-1] 5 | add ucitrack tuning_net 6 | set ucitrack.@tuning_net[-1].init=tuning_net 7 | commit ucitrack 8 | EOF 9 | 10 | exit 0 -------------------------------------------------------------------------------- /luci-alias.mk: -------------------------------------------------------------------------------- 1 | 2 | LUCI_LANG.zh-cn=简体中文 (Chinese Simplified) 3 | LUCI_LANG.zh-tw=繁體中文 (Chinese Traditional) 4 | LUCI_LANG.pt-br=Português do Brasil (Brazilian Portuguese) 5 | LUCI_LANG.no=Norsk (Norwegian) 6 | LUCI_LANG.bn=বাংলা (Bengali) 7 | 8 | include $(TOPDIR)/feeds/luci/luci.mk 9 | -------------------------------------------------------------------------------- /luci-app-fan/root/etc/uci-defaults/luci-fan: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /usr/libexec/fan-control init 4 | 5 | uci -q batch <<-EOF >/dev/null 6 | delete ucitrack.@luci-fan[-1] 7 | add ucitrack luci-fan 8 | set ucitrack.@luci-fan[-1].init=luci-fan 9 | commit ucitrack 10 | EOF 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /luci-lib-mac-vendor/src/Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | compile: 3 | install: 4 | mkdir -p "$(DESTDIR)/www/luci-static/resources/mac_vendor" 5 | cp -a "$(LIB_DIST)/." "$(DESTDIR)/www/luci-static/resources/mac_vendor/" 6 | $(SED) 's#=PKG_VERSION"#=$(LIB_VERSION)"#g' "$(DESTDIR)/www/luci-static/resources/mac_vendor/mac_vendor.js" 7 | -------------------------------------------------------------------------------- /luci-app-mergerfs/root/usr/share/luci/menu.d/luci-app-mergerfs.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin/nas/mergerfs": { 3 | "title": "MergerFS", 4 | "action": { 5 | "type": "view", 6 | "path": "mergerfs" 7 | }, 8 | "depends": { 9 | "acl": [ "luci-app-mergerfs" ], 10 | "uci": { "mergerfs": true } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /mergerfs/files/mergerfs.config: -------------------------------------------------------------------------------- 1 | config pool 2 | option enabled '0' 3 | option mountpoint '/mnt/merged/movies' 4 | option paths ' 5 | /mnt/nvme1/movies 6 | /mnt/nvme2/movies 7 | /mnt/nvme3/movies 8 | ' 9 | option createpolicy 'epmfs' 10 | option minfreespace '100M' 11 | # option options 'defaults,cache.files=off' 12 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/sb_guide.zh-cn.htm: -------------------------------------------------------------------------------- 1 |

当前不处于沙箱环境。沙箱配置方法:

2 | 8 |

注意:此沙箱实际是多层OverlayFS,方便用来实验系统配置和程序,方便开发未完成的软件,但不保护Docker和硬盘的数据

9 | -------------------------------------------------------------------------------- /luci-app-tasks/luasrc/controller/tasks-app.lua: -------------------------------------------------------------------------------- 1 | 2 | module("luci.controller.tasks-app", package.seeall) 3 | 4 | 5 | function index() 6 | entry({"admin", "system", "tasks"}, alias("admin", "system", "tasks", "all"), _("Tasks"), 56) 7 | --entry({"admin", "system", "tasks", "user"}, cbi("tasks/user"), _("User Tasks"), 1) 8 | entry({"admin", "system", "tasks", "all"}, form("tasks/all")) 9 | end 10 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/sb_guide.htm: -------------------------------------------------------------------------------- 1 |

Sandbox not working. How to start:

2 | 8 |

Note: this sandbox only protect overlay partition, no Docker or other disks included

9 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/sb_info.htm: -------------------------------------------------------------------------------- 1 |

Sandbox is working

2 |

Click "Commit" to merge changes to normal env, click "Reset" to reinitialize the sandbox

3 |

Click "Exit Sandbox" to exit sandbox env

4 |

Above actions will reboot device

5 |

Poweroff and detach the U disk to temporarily exit sandbox env

6 |

After developing app flashed, "Reset" sandbox so we can check the releaseed version

7 | -------------------------------------------------------------------------------- /luci-app-homebox/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Openwrt.org 2 | # 3 | # This is free software, licensed under the Apache License, Version 2.0 . 4 | # 5 | 6 | include $(TOPDIR)/rules.mk 7 | 8 | LUCI_TITLE:=LuCI support for homebox 9 | LUCI_DEPENDS:=+homebox 10 | LUCI_PKGARCH:=all 11 | PKG_VERSION:=1.0.1-r4 12 | PKG_RELEASE:= 13 | 14 | include ../luci-alias.mk 15 | 16 | # call BuildPackage - OpenWrt buildroot signature 17 | 18 | -------------------------------------------------------------------------------- /luci-app-mergerfs/Makefile: -------------------------------------------------------------------------------- 1 | # This is free software, licensed under the Apache License, Version 2.0 . 2 | 3 | include $(TOPDIR)/rules.mk 4 | 5 | LUCI_TITLE:=MergerFS 6 | LUCI_DEPENDS:=+luci-base +mergerfs 7 | 8 | LUCI_PKGARCH:=all 9 | 10 | PKG_VERSION:=1.0.3-r1 11 | PKG_RELEASE:= 12 | PKG_MAINTAINER:=jjm2473 13 | 14 | include ../luci-alias.mk 15 | 16 | # call BuildPackage - OpenWrt buildroot signature 17 | -------------------------------------------------------------------------------- /luci-app-tasks/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2022 jjm2473 3 | # 4 | # This is free software, licensed under the MIT License. 5 | # 6 | 7 | include $(TOPDIR)/rules.mk 8 | 9 | LUCI_TITLE:=luci for taskd 10 | LUCI_DEPENDS:=+luci-lib-taskd 11 | 12 | PKG_VERSION:=1.0.0 13 | PKG_RELEASE:= 14 | PKG_MAINTAINER:=jjm2473 15 | 16 | include ../luci-alias.mk 17 | 18 | # call BuildPackage - OpenWrt buildroot signature 19 | -------------------------------------------------------------------------------- /luci-app-cpufreq/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include $(TOPDIR)/rules.mk 3 | 4 | LUCI_TITLE:=LuCI for misc configure 5 | LUCI_PKGARCH:=all 6 | LUCI_DEPENDS:=+ethtool 7 | PKG_VERSION:=1.8.6-r3 8 | PKG_RELEASE:= 9 | 10 | define Package/luci-app-cpufreq/conffiles 11 | /etc/config/cpufreq 12 | /etc/config/tuning 13 | /etc/config/tuning_boot 14 | /etc/config/tuning_net 15 | endef 16 | 17 | include ../luci-alias.mk 18 | 19 | # call BuildPackage - OpenWrt buildroot signature 20 | -------------------------------------------------------------------------------- /luci-app-homebox/luasrc/model/cbi/homebox.lua: -------------------------------------------------------------------------------- 1 | 2 | local m, s 3 | 4 | m = Map("homebox", translate("Homebox"), translate("Homebox is a tool for local network speed testing")) 5 | 6 | m:section(SimpleSection).template = "homebox_status" 7 | 8 | s=m:section(TypedSection, "homebox", translate("Global Settings")) 9 | s.addremove=false 10 | s.anonymous=true 11 | 12 | s:option(Flag, "enabled", translate("Enable")).rmempty=false 13 | 14 | return m 15 | 16 | 17 | -------------------------------------------------------------------------------- /luci-app-mergerfs/root/usr/share/rpcd/acl.d/luci-app-mergerfs.json: -------------------------------------------------------------------------------- 1 | { 2 | "luci-app-mergerfs": { 3 | "description": "Grant access to LuCI app mergerfs", 4 | "read": { 5 | "ubus": { 6 | "luci": [ "getMountPoints" ] 7 | }, 8 | "uci": [ "mergerfs" ] 9 | }, 10 | "write": { 11 | "file": { 12 | "/bin/umount": [ "exec" ], 13 | "/etc/init.d/mergerfs reload": [ "exec" ] 14 | }, 15 | "uci": [ "mergerfs" ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/cpuinfo.htm: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 |

16 | <%:Collecting data...%> 17 |

18 |
-------------------------------------------------------------------------------- /luci-app-tasks/po/zh-cn/tasks.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | msgid "Tasks" 5 | msgstr "后台任务" 6 | 7 | msgid "All Tasks" 8 | msgstr "所有任务" 9 | 10 | msgid "All submitted tasks, including system defined tasks" 11 | msgstr "所有已提交的任务,包括系统定义的任务" 12 | 13 | msgid "Status" 14 | msgstr "状态" 15 | 16 | msgid "Running" 17 | msgstr "运行中" 18 | 19 | msgid "Stopped:" 20 | msgstr "已停止:" 21 | 22 | msgid "Start Time" 23 | msgstr "开始时间" 24 | 25 | msgid "Log" 26 | msgstr "日志" 27 | 28 | msgid "Remove" 29 | msgstr "移除" 30 | -------------------------------------------------------------------------------- /luci-app-fan/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Openwrt.org 2 | # 3 | # This is free software, licensed under the Apache License, Version 2.0 . 4 | # 5 | 6 | include $(TOPDIR)/rules.mk 7 | 8 | LUCI_TITLE:=LuCI fan control 9 | LUCI_DEPENDS:=+coreutils-stat 10 | LUCI_PKGARCH:=all 11 | PKG_VERSION:=1.0.0-r3 12 | PKG_RELEASE:= 13 | PKG_MAINTAINER:=jjm2473 14 | 15 | define Package/luci-app-fan/conffiles 16 | /etc/config/luci-fan 17 | endef 18 | 19 | include ../luci-alias.mk 20 | 21 | # call BuildPackage - OpenWrt buildroot signature 22 | 23 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/samba.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2021 jjm2473 4 | ]]-- 5 | 6 | local m, s, o 7 | 8 | m = Map("samba4", nil, translate("Samba")) 9 | 10 | s = m:section(TypedSection, "samba", translate("Samba expert")) 11 | s.addremove=false 12 | s.anonymous=true 13 | 14 | o = s:option(Flag, "allow_legacy_protocols", translate("Allow legacy protocols"), translate("Allow old client, don't use this option for secure environments!")) 15 | 16 | -- uci set samba.@samba[0].allow_legacy_protocols=1 17 | 18 | return m 19 | -------------------------------------------------------------------------------- /luci-app-homebox/po/zh-cn/homebox.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | msgid "Homebox" 5 | msgstr "Homebox" 6 | 7 | msgid "Click to open Homebox" 8 | msgstr "点击打开Homebox" 9 | 10 | msgid "Homebox is a tool for local network speed testing" 11 | msgstr "Homebox是一个局域网测速工具" 12 | 13 | msgid "The Homebox service is running." 14 | msgstr "Homebox服务已启动" 15 | 16 | msgid "The Homebox service is not running." 17 | msgstr "Homebox服务未启动" 18 | 19 | msgid "Homebox Status" 20 | msgstr "Homebox服务状态" 21 | 22 | msgid "Collecting data..." 23 | msgstr "收集数据..." 24 | 25 | -------------------------------------------------------------------------------- /homebox/files/homebox.init: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=99 4 | USE_PROCD=1 5 | 6 | get_config() { 7 | config_get_bool enabled $1 enabled 1 8 | config_get_bool logger $1 logger 9 | } 10 | 11 | start_service() { 12 | config_load homebox 13 | config_foreach get_config homebox 14 | [ $enabled != 1 ] && return 1 15 | 16 | procd_open_instance 17 | procd_set_param command /usr/bin/homebox 18 | [ "$logger" == 1 ] && procd_set_param stderr 1 19 | procd_set_param respawn 20 | procd_close_instance 21 | } 22 | 23 | service_triggers() { 24 | procd_add_reload_trigger "homebox" 25 | } 26 | -------------------------------------------------------------------------------- /mergerfs/files/mergerfs.fstab: -------------------------------------------------------------------------------- 1 | if /etc/init.d/mergerfs enabled && [ -f /etc/config/mergerfs ]; then 2 | ( 3 | . /lib/functions.sh 4 | 5 | add_paths() { 6 | local section="$1" 7 | local enabled paths 8 | 9 | config_get_bool enabled "$section" enabled 0 10 | [ "$enabled" -eq 1 ] || return 0 11 | 12 | config_get paths "$section" paths 13 | 14 | # ( 15 | printf "%s\n" "$paths" | while IFS= read -r p; do 16 | case "$p" in 17 | /*) fstab_add_essential_mountpoint "$p" 18 | ;; 19 | esac 20 | done 21 | } 22 | config_load mergerfs 23 | config_foreach add_paths pool 24 | ) 25 | fi 26 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/init.d/tuning: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=20 4 | 5 | ipk_config() { 6 | config_get ipk_mirror $1 mirror "disable" 7 | } 8 | 9 | start() { 10 | config_load tuning 11 | config_foreach ipk_config ipk 12 | 13 | if [ "$ipk_mirror" != "disable" -a -f "/rom/etc/opkg/distfeeds.conf" ]; then 14 | echo "# Generated file, do not edit" > /etc/opkg/distfeeds.conf 15 | cat "/rom/etc/opkg/distfeeds.conf" | \ 16 | sed -E 's# https?://[^ ]+/openwrt/# https://downloads.openwrt.org/#g' | \ 17 | sed -E 's#https?://downloads.openwrt.org/#'"$ipk_mirror"'#g' >> /etc/opkg/distfeeds.conf 18 | fi 19 | 20 | return 0 21 | } 22 | -------------------------------------------------------------------------------- /luci-app-fan/root/etc/init.d/luci-fan: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=20 4 | 5 | boot() { 6 | /usr/libexec/fan-control init 7 | start 8 | } 9 | 10 | start_instance() { 11 | local enabled 12 | config_get_bool enabled $1 enabled 0 13 | [[ "$enabled" = 1 ]] || return 0 14 | 15 | config_get on_temp $1 on_temp 16 | config_get off_temp $1 off_temp 17 | 18 | [[ -n "$on_temp" ]] && on_temp=${on_temp}000 19 | [[ -n "$off_temp" ]] && off_temp=${off_temp}000 20 | 21 | /usr/libexec/fan-control set "$on_temp" $off_temp 22 | } 23 | 24 | start() { 25 | config_load luci-fan 26 | config_foreach start_instance luci-fan 27 | return 0 28 | } 29 | -------------------------------------------------------------------------------- /mergerfs/patches/002-fix-install.patch: -------------------------------------------------------------------------------- 1 | diff --git a/libfuse/Makefile b/libfuse/Makefile 2 | index a20b0742..53959713 100644 3 | --- a/libfuse/Makefile 4 | +++ b/libfuse/Makefile 5 | @@ -136,8 +136,8 @@ strip: 6 | install-utils: mergerfs-fusermount mount.mergerfs strip 7 | install -D build/mergerfs-fusermount "$(INSTALLBINDIR)/mergerfs-fusermount" 8 | install -D build/mount.mergerfs "$(INSTALLSBINDIR)/mount.mergerfs" 9 | - chown root "$(INSTALLBINDIR)/mergerfs-fusermount" 10 | - chmod u+s "$(INSTALLBINDIR)/mergerfs-fusermount" 11 | +# chown root "$(INSTALLBINDIR)/mergerfs-fusermount" 12 | +# chmod u+s "$(INSTALLBINDIR)/mergerfs-fusermount" 13 | 14 | install: $(INSTALLUTILS) 15 | 16 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/init.d/cpufreq: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=20 4 | 5 | get_config() { 6 | config_get governor $1 governor 7 | config_get speed $1 speed 8 | } 9 | 10 | start() { 11 | config_load cpufreq 12 | config_foreach get_config cpufreq 13 | 14 | [[ -n "$governor" ]] || return 1 15 | 16 | local policy 17 | for policy in `ls /sys/devices/system/cpu/cpufreq/ | grep '^policy'`; do 18 | sh -c "echo '$governor' > /sys/devices/system/cpu/cpufreq/$policy/scaling_governor" 2>/dev/null 19 | [[ "$governor" = "userspace" && -n "$speed" ]] && sh -c "echo '$speed' > /sys/devices/system/cpu/cpufreq/$policy/scaling_setspeed" 2>/dev/null 20 | done 21 | 22 | return 0 23 | } -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/net.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2022 jjm2473 4 | ]]-- 5 | 6 | local m, s, o 7 | 8 | m = Map("tuning_net", nil, translate("Network")) 9 | 10 | s = m:section(TypedSection, "hw_acct", translate("Hardware Acceleration")) 11 | s.addremove=false 12 | s.anonymous=true 13 | 14 | o = s:option(Flag, "wan_acct", translate("Enable WAN Port Acceleration"), translate("Improve built-in WAN port (eth0) TX performace")) 15 | o.default="1" 16 | 17 | o = s:option(Flag, "hw_pppoe", translate("Enable PPPoE Acceleration"), translate("Improve PPPoE TX performace, only support built-in NICs")) 18 | o.rmempty=true 19 | o:depends('wan_acct', 1) 20 | 21 | return m 22 | -------------------------------------------------------------------------------- /luci-app-homebox/luasrc/controller/homebox.lua: -------------------------------------------------------------------------------- 1 | module("luci.controller.homebox", package.seeall) 2 | 3 | function index() 4 | if not nixio.fs.access("/etc/config/homebox") then 5 | return 6 | end 7 | 8 | entry({"admin", "services", "homebox"}, cbi("homebox"), _("Homebox"), 20).dependent = true 9 | 10 | entry({"admin", "services", "homebox_status"}, call("homebox_status")) 11 | end 12 | 13 | function homebox_status() 14 | local sys = require "luci.sys" 15 | local uci = require "luci.model.uci".cursor() 16 | 17 | local status = { 18 | running = (sys.call("pidof homebox >/dev/null 2>&1") == 0), 19 | port = 3300 20 | } 21 | 22 | luci.http.prepare_content("application/json") 23 | luci.http.write_json(status) 24 | end 25 | -------------------------------------------------------------------------------- /mergerfs/patches/003-fix-build-non-x86-target.patch: -------------------------------------------------------------------------------- 1 | From eebe9562d62e990dd80e7b5550492a2b4175cb44 Mon Sep 17 00:00:00 2001 2 | From: jjm2473 3 | Date: Thu, 7 Aug 2025 21:35:54 +0800 4 | Subject: [PATCH] fix build on openwrt arm64 target 5 | 6 | let openwrt handles stripping 7 | --- 8 | libfuse/Makefile | 4 ++-- 9 | 1 file changed, 2 insertions(+), 2 deletions(-) 10 | 11 | diff --git a/libfuse/Makefile b/libfuse/Makefile 12 | index 53959713..04e03396 100644 13 | --- a/libfuse/Makefile 14 | +++ b/libfuse/Makefile 15 | @@ -130,8 +130,8 @@ clean: 16 | distclean: clean 17 | 18 | strip: 19 | - strip --strip-all build/mount.mergerfs 20 | - strip --strip-all build/mergerfs-fusermount 21 | +# strip --strip-all build/mount.mergerfs 22 | +# strip --strip-all build/mergerfs-fusermount 23 | 24 | install-utils: mergerfs-fusermount mount.mergerfs strip 25 | install -D build/mergerfs-fusermount "$(INSTALLBINDIR)/mergerfs-fusermount" 26 | -- 27 | 2.46.0 28 | 29 | -------------------------------------------------------------------------------- /luci-app-homebox/luasrc/view/homebox_status.htm: -------------------------------------------------------------------------------- 1 | 21 | 22 |
23 | <%:Homebox Status%> 24 |

25 | <%:Collecting data...%> 26 |

27 |
28 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/init.d/tuning_net: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=19 4 | 5 | hwacct_config() { 6 | config_get wanacct_enabled $1 wan_acct "1" 7 | config_get hwpppoe_enabled $1 hw_pppoe "0" 8 | } 9 | 10 | boot() { 11 | local feature=`ethtool -k eth0 2>/dev/null | grep -F hw-pppoe: 2>/dev/null` 12 | [[ -n "$feature" ]] || return 1 13 | 14 | echo "$feature" | grep -qF '[fixed]' && return 1 15 | 16 | local hwpppoe_enabled 17 | local wanacct_enabled 18 | local hwpppoe=off 19 | local wanacct=on 20 | config_load tuning_net 21 | config_foreach hwacct_config hw_acct 22 | [ "$wanacct_enabled" = 0 ] && wanacct=off 23 | [ "$wanacct_enabled" = 1 -a "$hwpppoe_enabled" = 1 ] && hwpppoe=on 24 | 25 | ethtool -K eth0 hw-pppoe $hwpppoe tx-checksum-ip-generic $wanacct tx-scatter-gather $wanacct generic-receive-offload $wanacct 2>/dev/null 26 | ethtool -K eth1 hw-pppoe $hwpppoe 2>/dev/null 27 | 28 | return 0 29 | } 30 | 31 | start() { 32 | boot && /etc/init.d/network restart 33 | } 34 | -------------------------------------------------------------------------------- /luci-app-tasks/luasrc/view/tasks/all.htm: -------------------------------------------------------------------------------- 1 | <%+tasks/embed%> 2 | 3 | 29 | -------------------------------------------------------------------------------- /luci-lib-mac-vendor/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Openwrt.org 2 | # 3 | # This is free software, licensed under the Apache License, Version 2.0 . 4 | # 5 | 6 | include $(TOPDIR)/rules.mk 7 | 8 | LUCI_TITLE:=LuCI mac to vendor map 9 | LUCI_DESCRIPTION:=provide a js for mac address to vendor mapping 10 | LUCI_PKGARCH:=all 11 | 12 | PKG_VERSION:=1.0.0-r2 13 | # PKG_RELEASE MUST be empty for luci.mk 14 | PKG_RELEASE:= 15 | 16 | LIB_VERSION:=1.0.2 17 | PKG_HASH:=519ddb8a7a4d3b0e9b2fa5f01ffc7a20ef3af80201d6630c3fffc05e7374e0af 18 | 19 | PKG_SOURCE_URL_FILE:=v$(LIB_VERSION).tar.gz 20 | PKG_SOURCE:=mac_vendor-$(PKG_SOURCE_URL_FILE) 21 | PKG_SOURCE_URL:=https://github.com/jjm2473/mac_vendor/archive/refs/tags 22 | 23 | PKG_MAINTAINER:=jjm2473 24 | 25 | TARGET_CONFIGURE_OPTS= LIB_DIST="$(BUILD_DIR)/mac_vendor-$(LIB_VERSION)/dist" LIB_VERSION="$(LIB_VERSION)" 26 | TARGET_CONFIGURE_OPTS+= SED="$(SED)" 27 | 28 | include $(TOPDIR)/feeds/luci/luci.mk 29 | 30 | # call BuildPackage - OpenWrt buildroot signature 31 | 32 | -------------------------------------------------------------------------------- /ssd1306/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | I2C=$1 4 | [ -z "$I2C" ] && exit 1 5 | 6 | ROTATE=180 7 | # clear display every round for broken displays 8 | CLEAR=false 9 | 10 | LINELEN=21 # 128/6 11 | MAX=42 # 2 lines 12 | TEXT="Hello world!" 13 | 14 | 15 | len=`echo "$TEXT" | wc -c` 16 | if [ $len -gt $MAX ]; then 17 | echo "Text too long (max $MAX chars)" >&2 18 | exit 1 19 | fi 20 | fillround=$(( ($MAX + $len) / $len )). 21 | offset=0 22 | 23 | ssd1306 -n $I2C -I 128x32 24 | # rotate display 25 | ssd1306 -n $I2C -r $ROTATE 26 | if $CLEAR; then 27 | sleep 1 28 | else 29 | ssd1306 -n $I2C -c 30 | fi 31 | while :; do 32 | halfstart=$(($offset + $LINELEN)) 33 | text="" 34 | for i in $(seq 0 $fillround); do 35 | text="$text ${TEXT}" 36 | done 37 | $CLEAR && ssd1306 -n $I2C -c 38 | msg="`date '+%Y-%m-%d %H:%M:%S'`"' \n'"${text:$offset:$LINELEN}"'\n'"${text:$halfstart:$LINELEN}"'\n'"`date '+%Y-%m-%d %H:%M:%S'` " 39 | ssd1306 -n $I2C -m "$msg" 40 | sleep 1 41 | offset=$(( ($offset + 1) % $len )) 42 | done 43 | exit 0 44 | -------------------------------------------------------------------------------- /mergerfs/patches/001-fix-lto.patch: -------------------------------------------------------------------------------- 1 | diff --git a/libfuse/lib/fmt/format.h b/libfuse/lib/fmt/format.h 2 | index 7c607dbd..c08d6ca5 100644 3 | --- a/libfuse/lib/fmt/format.h 4 | +++ b/libfuse/lib/fmt/format.h 5 | @@ -1604,10 +1604,10 @@ auto snprintf_float(T value, int precision, float_specs specs, 6 | abort_fuzzing_if(precision > 100000); 7 | // Suppress the warning about a nonliteral format string. 8 | // Cannot use auto because of a bug in MinGW (#1532). 9 | - int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; 10 | + //int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; 11 | int result = precision >= 0 12 | - ? snprintf_ptr(begin, capacity, format, precision, value) 13 | - : snprintf_ptr(begin, capacity, format, value); 14 | + ? snprintf(begin, capacity, format, precision, value) 15 | + : snprintf(begin, capacity, format, value); 16 | if (result < 0) { 17 | // The buffer will grow exponentially. 18 | buf.try_reserve(buf.capacity() + 1); 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 练亮斌 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /luci-app-cpufreq/root/etc/init.d/await_fstab: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=11 4 | 5 | boot() { 6 | local enabled=`uci get tuning_boot.@fstab_delay[0].enabled 2>/dev/null` 7 | [ -z "$enabled" -o "$enabled" = 0 ] && return 0 8 | 9 | local timeout=`uci get tuning_boot.@fstab_delay[0].timeout 2>/dev/null` 10 | [ -z "$timeout" -o "$timeout" = 0 ] && return 0 11 | 12 | local devices=`uci get tuning_boot.@fstab_delay[0].device 2>/dev/null` 13 | 14 | if [ -n "$devices" ]; then 15 | echo "fstab_delay: wait up to $timeout seconds for device(s): $devices" >/dev/kmsg 16 | local i=0 17 | local dev 18 | local ready 19 | while [ $i -lt $timeout ]; do 20 | ready=1 21 | for dev in $devices ; do 22 | blkid --uuid $dev >/dev/null 2>&1 || { ready=0; break; } 23 | done 24 | [ $ready -eq 1 ] && break 25 | sleep 1 26 | i=$(($i+1)) 27 | done 28 | if [ $i -lt $timeout ]; then 29 | echo "fstab_delay: ready after $i seconds" >/dev/kmsg 30 | else 31 | echo "fstab_delay: wait device(s) timeout" >/dev/kmsg 32 | fi 33 | else 34 | echo "fstab_delay: sleep $timeout seconds before fstab" >/dev/kmsg 35 | sleep $timeout 36 | fi 37 | return 0 38 | } 39 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/kmods.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2023 jjm2473 4 | ]]-- 5 | 6 | local files = io.popen("ls /etc/modules-pending.d/", "r") 7 | local ln, drivers = nil, {} 8 | 9 | while ( true ) 10 | do 11 | ln = files:read("*l") 12 | if not ln or ln == "" then 13 | break 14 | end 15 | drivers[#drivers+1] = luci.util.trim(ln) 16 | end 17 | 18 | files:close() 19 | 20 | local m, s, o, i, d 21 | 22 | m = Map("kmods", nil, translate("Configure device drivers, kernel modules, etc. Changes here will take effect on next boot")) 23 | 24 | s = m:section(NamedSection, "kmods", "global", translate("Drivers Settings")) 25 | s.addremove=false 26 | s.anonymous=true 27 | 28 | local known = { 29 | ['r8125'] = translate("Realtek r8125 driver"), 30 | ['r8168'] = translate("Realtek r8168 driver"), 31 | ['i915-oot'] = translate("Backported Intel GPU driver (i915-oot)"), 32 | } 33 | 34 | o = s:option(StaticList, "enable", translate("Enable additional drivers"), translate("Please do not choose a driver you do not understand. Choosing the wrong driver may cause the system to fail to start")) 35 | for i, d in ipairs(drivers) do 36 | o:value(d, known[d] or d ) 37 | end 38 | 39 | return m 40 | -------------------------------------------------------------------------------- /ssd1306/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include $(TOPDIR)/rules.mk 3 | 4 | PKG_NAME:=ssd1306 5 | PKG_RELEASE:=1 6 | 7 | PKG_SOURCE_DATE:=2024-10-11 8 | PKG_SOURCE_VERSION:=19128ed4b6108408fea05b9d0551236b6d638dbc 9 | PKG_SOURCE:=ssd1306_linux-$(PKG_SOURCE_DATE).tar.gz 10 | PKG_SOURCE_URL:=https://codeload.github.com/armlabs/ssd1306_linux/tar.gz/$(PKG_SOURCE_VERSION)? 11 | PKG_HASH:=1cab77ce23e32c2740ab66ba40dda51b34ebbc28fabb477aad50102b3916b8c2 12 | 13 | PKG_MAINTAINER:=jjm2473 14 | PKG_LICENSE:=MIT 15 | PKG_LICENSE_FILES:=LICENSE 16 | 17 | include $(INCLUDE_DIR)/package.mk 18 | 19 | define Package/ssd1306 20 | SECTION:=utils 21 | CATEGORY:=Utilities 22 | TITLE:=SSD1306 OLED I2C Driver 23 | URL:=https://github.com/armlabs/ssd1306_linux 24 | endef 25 | 26 | define Package/ssd1306/description 27 | SSD1306 oled I2C driver working in linux 28 | endef 29 | 30 | TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS) 31 | TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS) 32 | 33 | define Package/ssd1306/install 34 | $(INSTALL_DIR) $(1)/usr/bin 35 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/ssd1306 $(1)/usr/bin 36 | endef 37 | 38 | # Set variables used in the source's Makefile 39 | MAKE_FLAGS+= BIN="ssd1306" LDFLAGS="" 40 | 41 | $(eval $(call BuildPackage,ssd1306)) 42 | -------------------------------------------------------------------------------- /luci-app-fan/luasrc/view/luci-fan.htm: -------------------------------------------------------------------------------- 1 |
2 |
3 |

<%:Status%>

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
<%:Thermal zone%><%=self.thermal_zone%> (<%:type:%> <%=self.thermal_type%>)
<%:Trip point%>trip_point_<%=self.trip_point%>
<%:Fan start temperature%>
<%:Current temperature%>
12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /luci-app-fan/luasrc/controller/admin/luci-fan.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2023 jjm2473 4 | ]]-- 5 | 6 | module("luci.controller.admin.luci-fan", package.seeall) 7 | 8 | function index() 9 | require "luci.sys" 10 | local appname = "luci-fan" 11 | local defaultpage = nil 12 | if luci.sys.call("/usr/libexec/fan-control get >/dev/null 2>&1") == 0 then 13 | entry({"admin", "system", appname}, cbi("luci-fan"), _("Fan Control"), 60) 14 | else 15 | entry({"admin", "system", appname}).dependent = true 16 | end 17 | entry({"admin", "system", appname, "get_fan_info"}, call("get_fan_info"), nil).leaf = true 18 | end 19 | 20 | function get_fan_info(zone, trip) 21 | require "luci.util" 22 | local words 23 | if zone and trip and string.match(zone, "^thermal_zone%d+$") and string.match(trip, "^%d+$") then 24 | local fs = require "nixio.fs" 25 | words = { 26 | luci.util.trim(fs.readfile("/sys/class/thermal/"..zone.."/temp")), 27 | luci.util.trim(fs.readfile("/sys/class/thermal/"..zone.."/trip_point_"..trip.."_temp")) 28 | } 29 | else 30 | local sys = require "luci.sys" 31 | words = luci.util.split(luci.util.trim(sys.exec("/usr/libexec/fan-control temp 2>/dev/null")), " ") 32 | end 33 | local zone_temp = tonumber(words[1]) / 1000; -- ˚C 34 | local fan_on_temp = tonumber(words[2]) / 1000; -- ˚C 35 | luci.http.status(200, "ok") 36 | luci.http.prepare_content("application/json") 37 | luci.http.write_json({zone_temp=zone_temp, fan_on_temp=fan_on_temp}) 38 | end 39 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/ipk.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2021 jjm2473 4 | ]]-- 5 | 6 | local m, s, o 7 | 8 | m = Map("tuning", nil, translate("Select IPK Mirror server")) 9 | 10 | s = m:section(TypedSection, "ipk") 11 | s.addremove=false 12 | s.anonymous=true 13 | 14 | o = s:option(ListValue, "mirror", translate("Mirror server")) 15 | o:value("disable", "") 16 | o:value("http://downloads.openwrt.org/", translate("OpenWRT") .. " (HTTP)") 17 | o:value("https://downloads.openwrt.org/", translate("OpenWRT") .. " (HTTPS)") 18 | o:value("https://mirrors.cernet.edu.cn/openwrt/", translate("CERNET 302")) 19 | o:value("https://mirrors.sustech.edu.cn/openwrt/", translate("SUSTech")) 20 | o:value("https://mirrors.tuna.tsinghua.edu.cn/openwrt/", translate("Tsinghua University")) 21 | o:value("https://mirrors.ustc.edu.cn/openwrt/", translate("USTC")) 22 | o:value("https://mirror.lzu.edu.cn/openwrt/", translate("Lanzhou University")) 23 | o:value("https://mirrors.aliyun.com/openwrt/", translate("Alibaba Cloud")) 24 | o:value("https://mirrors.cloud.tencent.com/openwrt/", translate("Tencent Cloud")) 25 | o:value("https://mirror.iscas.ac.cn/openwrt/", translate("Chinese Academy of Sciences")) 26 | o:value("https://mirror.nyist.edu.cn/openwrt/", translate("NYIST")) 27 | o:value("https://mirror.sjtu.edu.cn/openwrt/", translate("SJTU")) 28 | o:value("https://mirrors.cqupt.edu.cn/openwrt/", translate("CQUPT")) 29 | o:value("https://mirrors.qlu.edu.cn/openwrt/", translate("Qilu University of Technology")) 30 | 31 | o.rmempty = false 32 | o.default = "disable" 33 | 34 | return m 35 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/main.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2021 jjm2473 4 | ]]-- 5 | 6 | local m, s, o 7 | require "luci.util" 8 | 9 | local governor_path = "/sys/devices/system/cpu/cpufreq/policy0/scaling_governor" 10 | 11 | local fs = require "nixio.fs" 12 | 13 | m = Map("cpufreq", nil, translate("Manage CPU performance over LuCI.")) 14 | m:section(SimpleSection).template = "cpufreq/cpuinfo" 15 | 16 | s = m:section(TypedSection, "cpufreq") 17 | s.addremove=false 18 | s.anonymous=true 19 | 20 | local cur_governor = luci.util.trim(fs.readfile(governor_path)) 21 | 22 | o = s:option(ListValue, "governor", translate("CPUFreq governor"), translate("It is recommended to use 'ondemand' or 'schedutil'")) 23 | o:value("", translate("Default (Take effect after reboot)")) 24 | for i,v in pairs(luci.util.split(luci.util.trim(fs.readfile("/sys/devices/system/cpu/cpufreq/policy0/scaling_available_governors")), " ")) do 25 | o:value(v, translate(v)) 26 | end 27 | o.default = cur_governor 28 | 29 | local available_frequencies = luci.util.split(luci.util.trim(fs.readfile("/sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies")), " ") 30 | 31 | if #available_frequencies > 0 then 32 | o = s:option(ListValue, "speed", translate("Frequency"), translate("Pay attention to heat dissipation when choosing high frequency")) 33 | o:depends("governor", "userspace") 34 | for i,v in pairs(available_frequencies) do 35 | o:value(v, (tonumber(v)/1000) .. " MHz") 36 | end 37 | o.rmempty = true 38 | o.default = available_frequencies[1] 39 | end 40 | 41 | return m 42 | -------------------------------------------------------------------------------- /nvtop/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include $(TOPDIR)/rules.mk 3 | 4 | PKG_NAME:=nvtop 5 | PKG_VERSION:=3.2.0 6 | PKG_RELEASE:=2 7 | 8 | PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz 9 | PKG_SOURCE_URL:=https://codeload.github.com/Syllo/$(PKG_NAME)/tar.gz/$(PKG_VERSION)? 10 | PKG_HASH:=d26df685455023cedc4dda033862dcddb67402fbdb685da70da78492f73c41d0 11 | 12 | PKG_MAINTAINER:=jjm2473 13 | PKG_LICENSE:=GPL-3.0+ 14 | 15 | PKG_CONFIG_DEPENDS:= \ 16 | CONFIG_LIBDRM_AMDGPU 17 | 18 | include $(INCLUDE_DIR)/package.mk 19 | include $(INCLUDE_DIR)/cmake.mk 20 | 21 | define Package/nvtop 22 | SECTION:=utils 23 | CATEGORY:=Utilities 24 | TITLE:=NVTOP 25 | DEPENDS:=@(aarch64||x86_64) +libncursesw +libudev +libdrm 26 | URL:=https://github.com/Syllo/nvtop 27 | endef 28 | 29 | define Package/nvtop/description 30 | NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for GPUs and accelerators 31 | endef 32 | 33 | TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include 34 | 35 | CMAKE_OPTIONS += \ 36 | -DUSE_LIBUDEV_OVER_LIBSYSTEMD=ON \ 37 | -DAPPLE_SUPPORT=OFF \ 38 | -DNVIDIA_SUPPORT=OFF \ 39 | -DASCEND_SUPPORT=OFF \ 40 | -DTPU_SUPPORT=OFF 41 | 42 | ifdef CONFIG_aarch64 43 | CMAKE_OPTIONS += \ 44 | -DPANFROST_SUPPORT=ON \ 45 | -DPANTHOR_SUPPORT=ON \ 46 | -DAMDGPU_SUPPORT=OFF \ 47 | -DINTEL_SUPPORT=OFF 48 | else 49 | CMAKE_OPTIONS += \ 50 | -DPANFROST_SUPPORT=OFF \ 51 | -DPANTHOR_SUPPORT=OFF \ 52 | -DAMDGPU_SUPPORT=$(if $(CONFIG_LIBDRM_AMDGPU),ON,OFF) \ 53 | -DINTEL_SUPPORT=ON \ 54 | -DV3D_SUPPORT=OFF 55 | endif 56 | 57 | define Package/nvtop/install 58 | $(INSTALL_DIR) $(1)/usr/bin 59 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nvtop $(1)/usr/bin/ 60 | endef 61 | 62 | $(eval $(call BuildPackage,nvtop)) 63 | -------------------------------------------------------------------------------- /luci-app-tasks/luasrc/model/cbi/tasks/all.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | ]]-- 4 | 5 | local taskd = require "luci.model.tasks" 6 | local tasks = taskd.status() 7 | local show_log_taskid 8 | local m, s, o 9 | 10 | local t=Template("tasks/all") 11 | 12 | m = SimpleForm("taskd", 13 | translate("All Tasks"), 14 | translate("All submitted tasks, including system defined tasks")) 15 | m.submit=false 16 | m.reset=false 17 | 18 | s = m:section(Table, tasks) 19 | s.config = "tasks" 20 | 21 | o = s:option(DummyValue, "_id", translate("ID")) 22 | o.width="10%" 23 | o.cfgvalue = function(self, section) 24 | return section 25 | end 26 | 27 | o = s:option(DummyValue, "_status", translate("Status")) 28 | o.width="15%" 29 | o.cfgvalue = function(self, section) 30 | local task = tasks[section] 31 | return task.running and translate("Running") or (translate("Stopped:") .. " " .. task.exit_code) 32 | end 33 | 34 | o = s:option(DummyValue, "_start", translate("Start Time")) 35 | o.width="15%" 36 | o.cfgvalue = function(self, section) 37 | local task = tasks[section] 38 | return os.date("%Y/%m/%d %H:%M:%S", task.start) 39 | end 40 | -- os.date("%Y/%m/%d %H:%M:%S", 1657163212) 41 | 42 | local btn_log = s:option(Button, "_log", translate("Log")) 43 | btn_log.inputstyle = "find" 44 | btn_log.write = function(self, section, value) 45 | t.show_log_taskid = section 46 | end 47 | 48 | local btn_remove = s:option(Button, "_remove", translate("Remove")) 49 | btn_remove.inputstyle = "remove" 50 | btn_remove.forcewrite = true 51 | btn_remove.write = function(self, section, value) 52 | local task_id = section 53 | os.execute("/etc/init.d/tasks task_del "..task_id.." >/dev/null 2>&1") 54 | tasks[task_id] = nil 55 | end 56 | 57 | m:append(t) 58 | 59 | return m 60 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/boot.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2021 jjm2473 4 | ]]-- 5 | 6 | local fs = require "nixio.fs" 7 | 8 | local block = io.popen("block info", "r") 9 | local ln, dev, devices = nil, nil, {} 10 | 11 | repeat 12 | ln = block:read("*l") 13 | dev = ln and ln:match("^/dev/(.-):") 14 | 15 | if dev then 16 | local e, s, key, val = { } 17 | 18 | for key, val in ln:gmatch([[(%w+)="(.-)"]]) do 19 | e[key:lower()] = val 20 | end 21 | 22 | s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev))) 23 | 24 | e.dev = "/dev/%s" % dev 25 | e.size = s and math.floor(s / 2048) 26 | 27 | devices[#devices+1] = e 28 | end 29 | until not ln 30 | 31 | block:close() 32 | 33 | 34 | local m, s, o 35 | 36 | m = Map("tuning_boot", nil, translate("Boot")) 37 | 38 | s = m:section(TypedSection, "fstab_delay", translate("Delay before disk mounting"), 39 | translate("Wait for the hard disk to initialize to solve the problem that the hard disk is not mounted when some applications that rely on the hard disk are started.") 40 | .. "
" .. translate("Do not select a network block device (e.g. NBD, iSCSI, etc.), you may have to wait until timeout.")) 41 | s.addremove=false 42 | s.anonymous=true 43 | 44 | o = s:option(Flag, "enabled", translate("Enable")) 45 | 46 | o = s:option(Value, "timeout", translate("Timeout (seconds)")) 47 | o:value("5", "5") 48 | o:value("10", "10") 49 | o:value("30", "30") 50 | o:value("60", "60") 51 | o:depends("enabled", 1) 52 | o.default = "5" 53 | 54 | o = s:option(DynamicList, "device", translate("Or until these device(s) ready (UUID):")) 55 | o:depends("enabled", 1) 56 | for i, d in ipairs(devices) do 57 | if d.uuid and d.size then 58 | o:value(d.uuid, "%s (%s, %d MB)" %{ d.uuid, d.dev, d.size }) 59 | elseif d.uuid then 60 | o:value(d.uuid, "%s (%s)" %{ d.uuid, d.dev }) 61 | end 62 | end 63 | 64 | return m 65 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/model/cbi/cpufreq/cmdline.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2024 jjm2473 4 | ]]-- 5 | 6 | require "luci.util" 7 | require "luci.xml" 8 | local fs = require "nixio.fs" 9 | 10 | local m, s, o 11 | 12 | m = Map("grub", nil, translate("This page configures Linux kernel boot parameters. After saving and applying, the GRUB configuration file of the boot partition will be modified. The parameters will take effect after restarting the system (the boot partition is not within the scope of sandbox protection, please be aware)")) 13 | s = m:section(SimpleSection, translate("Current Cmdline"), luci.xml.pcdata(luci.util.trim(fs.readfile("/proc/cmdline") or ""))) 14 | 15 | if fs.access("/etc/grub.cfg.d/01-iommu.cfg") then 16 | s = m:section(NamedSection, "iommu", "iommu", "IOMMU", translate("Supports PCI device passthrough for virtual machines (KVM/QEMU)")) 17 | s.addremove=false 18 | s.anonymous=true 19 | 20 | o = s:option(Flag, "enabled", translate("Enabled")) 21 | 22 | o = s:option(Value, "cmdline", translate("Parameters"), translate("Default or empty will be automatically filled in according to the current platform")) 23 | o:value("", translate("Default")) 24 | o:value("intel_iommu=on iommu=pt", "Intel (intel_iommu=on iommu=pt)") 25 | o:value("amd_iommu=on iommu=pt", "AMD (amd_iommu=on iommu=pt)") 26 | 27 | end 28 | 29 | s = m:section(TypedSection, "cmdline", translate("Custom Parameters"), 30 | translate("Danger! If you do not understand the kernel boot parameters, do not modify them to avoid being unable to start or damaging the hardware")) 31 | s.addremove=true 32 | s.anonymous=true 33 | s.template = "cbi/tblsection" 34 | 35 | o = s:option(Flag, "enabled", translate("Enabled")) 36 | 37 | o = s:option(Value, "cmdline", translate("Parameters")) 38 | o.datatype = "string" 39 | o.rmempty = false 40 | 41 | o = s:option(Value, "comment", translate("Comment")) 42 | 43 | return m 44 | -------------------------------------------------------------------------------- /duperemove/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is free software, licensed under the GNU General Public License v2. 3 | # See /LICENSE for more information. 4 | # 5 | 6 | include $(TOPDIR)/rules.mk 7 | 8 | PKG_NAME:=duperemove 9 | PKG_VERSION:=0.15.1 10 | PKG_RELEASE:=1 11 | 12 | PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz 13 | PKG_SOURCE_URL:=https://codeload.github.com/markfasheh/duperemove/tar.gz/v$(PKG_VERSION)? 14 | PKG_HASH:=68cc28f5aa43fa2034e512f7b22cf5282ce2b0319b4e1061f7cdf55cc134273b 15 | 16 | PKG_MAINTAINER:=Mark Fasheh 17 | PKG_LICENSE:=GPL-2.0 18 | PKG_LICENSE_FILES:=LICENSE 19 | 20 | include $(INCLUDE_DIR)/package.mk 21 | 22 | define Package/duperemove 23 | SECTION:=utils 24 | CATEGORY:=Utilities 25 | SUBMENU:=Filesystem 26 | TITLE:=Duplicate file removal tool 27 | URL:=https://github.com/markfasheh/duperemove 28 | DEPENDS:= \ 29 | +libsqlite3 \ 30 | +glib2 \ 31 | +libxxhash \ 32 | +libuuid \ 33 | +libmount \ 34 | +libblkid \ 35 | +libbsd \ 36 | +libatomic 37 | endef 38 | 39 | define Package/duperemove/description 40 | Duperemove is a simple tool for finding duplicated extents and submitting 41 | them for deduplication. When given a list of files it will hash their 42 | contents on an extent by extent basis and compare those hashes to each 43 | other, finding and categorizing extents that match each other. Optionally, 44 | a per-block hash can be applied for further duplication lookup. When given 45 | the -d option, duperemove will submit those extents for deduplication using 46 | the Linux kernel FIDEDUPRANGE ioctl. 47 | endef 48 | 49 | define Package/duperemove/install 50 | $(INSTALL_DIR) $(1)/usr/bin 51 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/duperemove $(1)/usr/bin 52 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/hashstats $(1)/usr/bin 53 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/btrfs-extent-same $(1)/usr/bin 54 | endef 55 | 56 | # Set variables used in the source's Makefile 57 | MAKE_FLAGS+= VERSION="$(PKG_VERSION)" IS_RELEASE=1 58 | 59 | $(eval $(call BuildPackage,duperemove)) 60 | -------------------------------------------------------------------------------- /mergerfs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include $(TOPDIR)/rules.mk 3 | 4 | PKG_NAME:=mergerfs 5 | PKG_VERSION:=2.40.2 6 | PKG_RELEASE:=5 7 | 8 | PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz 9 | PKG_SOURCE_URL:=https://github.com/trapexit/mergerfs/releases/download/$(PKG_VERSION)/ 10 | PKG_HASH:=595a7a108f5a20e0cd20b6d08a360b283940d81b1a66b118d27dfa93540878b0 11 | 12 | PKG_MAINTAINER:=jjm2473 13 | PKG_LICENSE:=ISC 14 | PKG_LICENSE_FILES:=LICENSE 15 | 16 | PKG_INSTALL:=1 17 | 18 | include $(INCLUDE_DIR)/package.mk 19 | 20 | define Package/mergerfs 21 | SECTION:=utils 22 | CATEGORY:=Utilities 23 | SUBMENU:=Filesystem 24 | TITLE:=A featureful union filesystem 25 | URL:=https://github.com/trapexit/mergerfs 26 | DEPENDS:=+libstdcpp 27 | endef 28 | 29 | define Package/mergerfs/description 30 | mergerfs is a FUSE based union filesystem geared towards simplifying 31 | storage and management of files across numerous commodity storage 32 | devices. It is similar to mhddfs, unionfs, and aufs. 33 | endef 34 | 35 | define Package/mergerfs/conffiles 36 | /etc/config/mergerfs 37 | endef 38 | 39 | define Package/mergerfs/install 40 | $(INSTALL_DIR) $(1)/sbin/fs $(1)/usr/bin $(1)/usr/lib/mergerfs 41 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/mount.mergerfs $(1)/sbin/ 42 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mergerfs-fusermount $(1)/usr/bin/ 43 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mergerfs $(1)/usr/bin/ 44 | $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/mergerfs/preload.so $(1)/usr/lib/mergerfs/ 45 | $(LN) /sbin/mount.mergerfs $(1)/sbin/fs/mount.mergerfs 46 | 47 | $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d $(1)/lib/fstab.d 48 | $(INSTALL_CONF) ./files/mergerfs.config $(1)/etc/config/mergerfs 49 | $(INSTALL_BIN) ./files/mergerfs.init $(1)/etc/init.d/mergerfs 50 | $(INSTALL_DATA) ./files/mergerfs.fstab $(1)/lib/fstab.d/mergerfs.sh 51 | endef 52 | 53 | # Set variables used in the source's Makefile 54 | MAKE_FLAGS+= NDEBUG=1 USE_XATTR=0 LTO=1 PREFIX=/usr 55 | 56 | $(eval $(call BuildPackage,mergerfs)) 57 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/view/cpufreq/sandbox.htm: -------------------------------------------------------------------------------- 1 | 2 | <%+header%> 3 | 4 |

<%:Sandbox%>

5 |
<%:Simple sandbox for OpenWRT%>
6 | 7 | <% 8 | 9 | local sys = require "luci.sys" 10 | 11 | local insandbox = sys.call("/usr/sbin/sandbox status 2>/dev/null") == 0 12 | 13 | if insandbox then 14 | %> 15 | 16 |
17 | <% luci.template.render(translate("cpufreq/sb_info")) %> 18 |
19 | 20 |
21 | 22 | 55 | 56 |
57 | 58 | 59 | 60 |
61 | 62 | 66 | 67 | <% else %> 68 | 69 |
70 | <% luci.template.render(translate("cpufreq/sb_guide")) %> 71 |
72 | 73 | <% end %> 74 | 75 | <%+footer%> 76 | -------------------------------------------------------------------------------- /luci-app-cpufreq/po/en/cpufreq.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | msgid "Tuning" 5 | msgstr "Tuning" 6 | 7 | msgid "CPU Tuning" 8 | msgstr "CPU Tuning" 9 | 10 | msgid "Manage CPU performance over LuCI." 11 | msgstr "Manage CPU performance over LuCI." 12 | 13 | msgid "CPU frequence:" 14 | msgstr "CPU frequence:" 15 | 16 | msgid "temperature:" 17 | msgstr "temperature:" 18 | 19 | msgid "CPUFreq governor" 20 | msgstr "CPUFreq governor" 21 | 22 | msgid "Default (Take effect after reboot)" 23 | msgstr "Default (Take effect after reboot)" 24 | 25 | msgid "conservative" 26 | msgstr "Conservative" 27 | 28 | msgid "userspace" 29 | msgstr "Userspace" 30 | 31 | msgid "powersave" 32 | msgstr "Powersave" 33 | 34 | msgid "ondemand" 35 | msgstr "Ondemand" 36 | 37 | msgid "performance" 38 | msgstr "Performance" 39 | 40 | msgid "interactive" 41 | msgstr "Interactive" 42 | 43 | msgid "Fan trigger temperature" 44 | msgstr "Fan trigger temperature" 45 | 46 | msgid "IPK Mirror" 47 | msgstr "IPK Mirror" 48 | 49 | msgid "Select IPK Mirror server" 50 | msgstr "Select IPK Mirror server" 51 | 52 | msgid "Mirror server" 53 | msgstr "Mirror server" 54 | 55 | msgid "Tsinghua University" 56 | msgstr "Tsinghua University" 57 | 58 | msgid "USTC" 59 | msgstr "USTC" 60 | 61 | msgid "Alibaba Cloud" 62 | msgstr "Alibaba Cloud" 63 | 64 | msgid "Tencent Cloud" 65 | msgstr "Tencent Cloud" 66 | 67 | msgid "Drivers" 68 | msgstr "Drivers" 69 | 70 | msgid "Drivers Settings" 71 | msgstr "Drivers Settings" 72 | 73 | msgid "Realtek r8125 driver" 74 | msgstr "Realtek r8125 driver" 75 | 76 | msgid "Realtek r8168 driver" 77 | msgstr "Realtek r8168 driver" 78 | 79 | msgid "Backported Intel GPU driver (i915-oot)" 80 | msgstr "Backported Intel GPU driver (i915-oot)" 81 | 82 | msgid "Enable additional drivers" 83 | msgstr "Enable additional drivers" 84 | 85 | msgid "Configure device drivers, kernel modules, etc. Changes here will take effect on next boot" 86 | msgstr "Configure device drivers, kernel modules, etc. Changes here will take effect on next boot" 87 | 88 | msgid "Please do not choose a driver you do not understand. Choosing the wrong driver may cause the system to fail to start" 89 | msgstr "Please do not choose a driver you do not understand. Choosing the wrong driver may cause the system to fail to start" 90 | -------------------------------------------------------------------------------- /luci-app-fan/po/templates/luci-fan.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:19 5 | msgid "" 6 | "Control fan start and stop temperature. This plugin can only configure the " 7 | "lowest gear, not necessarily applicable to all devices." 8 | msgstr "" 9 | 10 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:9 11 | msgid "Current temperature" 12 | msgstr "" 13 | 14 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:31 15 | msgid "Enabled" 16 | msgstr "" 17 | 18 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/controller/admin/luci-fan.lua:13 19 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:19 20 | msgid "Fan Control" 21 | msgstr "" 22 | 23 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:27 24 | msgid "Fan Settings" 25 | msgstr "" 26 | 27 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:34 28 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:8 29 | msgid "Fan start temperature" 30 | msgstr "" 31 | 32 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:42 33 | msgid "Fan stop temperature" 34 | msgstr "" 35 | 36 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:80 37 | msgid "Fan stop temperature MUST be lower than fan start temperature" 38 | msgstr "" 39 | 40 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:42 41 | msgid "" 42 | "Optional, MUST be lower than the fan start temperature. Default fan start " 43 | "temperature minus 5 ℃" 44 | msgstr "" 45 | 46 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:3 47 | msgid "Status" 48 | msgstr "" 49 | 50 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:6 51 | msgid "Thermal zone" 52 | msgstr "" 53 | 54 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:7 55 | msgid "Trip point" 56 | msgstr "" 57 | 58 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:31 59 | msgid "Whether to apply the settings" 60 | msgstr "" 61 | 62 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:6 63 | msgid "type:" 64 | msgstr "" 65 | -------------------------------------------------------------------------------- /mergerfs/files/mergerfs.init: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | # mergerfs -f -o category.create=epmfs,minfreespace=100M,fsname=mergerfs:/mnt/merged /mnt/n2:/mnt/n3:/mnt/n4 /mnt/merged 4 | 5 | START=98 6 | 7 | USE_PROCD=1 8 | 9 | start_service() { 10 | config_load mergerfs 11 | config_foreach start_pool pool 12 | } 13 | 14 | start_pool() { 15 | local section="$1" 16 | local enabled mountpoint paths createpolicy minfreespace options 17 | 18 | config_get_bool enabled "$section" enabled 0 19 | [ "$enabled" -eq 1 ] || return 0 20 | config_get mountpoint "$section" mountpoint 21 | config_get paths "$section" paths 22 | config_get createpolicy "$section" createpolicy "epmfs" 23 | config_get minfreespace "$section" minfreespace "4G" 24 | config_get options "$section" options 25 | 26 | # 检查 mountpoint 是否已设置 27 | [ -z "$mountpoint" ] && { 28 | logger -t "mergerfs" "mountpoint not set for $section" 29 | return 1 30 | } 31 | 32 | # ( 33 | printf "%s\n" "$paths" | while IFS= read -r p; do 34 | case "$p" in 35 | /*) 36 | if [ ! -d "$p" ]; then 37 | logger -t "mergerfs" "source path $p does not exist for $mountpoint" 38 | return 1 39 | fi 40 | ;; 41 | esac 42 | done || return 1 43 | 44 | # 只保留以 / 开头的路径,拼接为冒号分隔的字符串 45 | srcs=$( 46 | # ( 47 | printf "%s\n" "$paths" | while IFS= read -r p; do 48 | case "$p" in 49 | /*) printf ':%s' "$p" ;; 50 | esac 51 | done 52 | ) 53 | srcs="${srcs#:}" 54 | 55 | [ -z "$srcs" ] && { 56 | logger -t "mergerfs" "no valid source paths for $mountpoint" 57 | return 1 58 | } 59 | 60 | local opts 61 | opts="category.create=${createpolicy},minfreespace=${minfreespace},fsname=mergerfs:${mountpoint}" 62 | [ -n "$options" ] && opts="${opts},${options}" 63 | 64 | mkdir -p "$mountpoint" 65 | # mountpoint -q "$mountpoint" && umount "$mountpoint" 66 | 67 | logger -t "mergerfs" "mergerfs -o $opts \"$srcs\" \"$mountpoint\"" 68 | 69 | procd_open_instance "$section" 70 | procd_set_param command /usr/bin/mergerfs -f -o "$opts" "$srcs" "$mountpoint" 71 | procd_close_instance 72 | # close flock fd, or the script will hangs next time it runs 73 | # ( exec 1000>&- ; mergerfs -o "$opts" "$srcs" "$mountpoint" ) 74 | } 75 | 76 | stop_service() { 77 | config_load mergerfs 78 | config_foreach stop_pool pool 79 | } 80 | 81 | stop_pool() { 82 | local section="$1" 83 | local mountpoint 84 | config_get mountpoint "$section" mountpoint 85 | [ -n "$mountpoint" ] && umount "$mountpoint" 86 | } 87 | 88 | service_triggers() { 89 | procd_add_reload_trigger "mergerfs" 90 | } 91 | -------------------------------------------------------------------------------- /luci-app-fan/po/zh-cn/luci-fan.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Language: zh_Hans\n" 4 | "Content-Type: text/plain; charset=UTF-8\n" 5 | "Content-Transfer-Encoding: 8bit\n" 6 | "Plural-Forms: nplurals=1; plural=0;\n" 7 | 8 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:19 9 | msgid "" 10 | "Control fan start and stop temperature. This plugin can only configure the " 11 | "lowest gear, not necessarily applicable to all devices." 12 | msgstr "控制风扇启停温度。此插件仅配置最低档位触发点,不一定适用于所有设备" 13 | 14 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:9 15 | msgid "Current temperature" 16 | msgstr "当前温度" 17 | 18 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:31 19 | msgid "Enabled" 20 | msgstr "启用" 21 | 22 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/controller/admin/luci-fan.lua:13 23 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:19 24 | msgid "Fan Control" 25 | msgstr "风扇控制" 26 | 27 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:27 28 | msgid "Fan Settings" 29 | msgstr "风扇设置" 30 | 31 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:34 32 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:8 33 | msgid "Fan start temperature" 34 | msgstr "风扇启动温度" 35 | 36 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:42 37 | msgid "Fan stop temperature" 38 | msgstr "风扇停止温度" 39 | 40 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:80 41 | msgid "Fan stop temperature MUST be lower than fan start temperature" 42 | msgstr "风扇停止温度必须小于风扇启动温度" 43 | 44 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:42 45 | msgid "" 46 | "Optional, MUST be lower than the fan start temperature. Default fan start " 47 | "temperature minus 5 ℃" 48 | msgstr "可选,必须小于风扇启动温度。默认风扇启动温度减 5 ℃" 49 | 50 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:3 51 | msgid "Status" 52 | msgstr "状态" 53 | 54 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:6 55 | msgid "Thermal zone" 56 | msgstr "温感区" 57 | 58 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:7 59 | msgid "Trip point" 60 | msgstr "触发点" 61 | 62 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/model/cbi/luci-fan.lua:31 63 | msgid "Whether to apply the settings" 64 | msgstr "是否应用此设置" 65 | 66 | #: /Volumes/data/src/nas-packages-luci/luci/luci-app-fan/luasrc/view/luci-fan.htm:6 67 | msgid "type:" 68 | msgstr "类型:" 69 | -------------------------------------------------------------------------------- /homebox/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/rules.mk 2 | 3 | PKG_NAME:=homebox 4 | PKG_VERSION:=0.0.0_pre2020062901 5 | PKG_RELEASE:=3 6 | 7 | SRC_VERSION:=0.0.0-dev.2020062901 8 | PKG_SOURCE_URL_FILE:=v$(SRC_VERSION).tar.gz 9 | PKG_SOURCE:=$(PKG_NAME)-$(SRC_VERSION).tar.gz 10 | PKG_SOURCE_URL:=https://github.com/XGHeaven/homebox/archive/refs/tags/ 11 | PKG_HASH:=815a2a0fc5458245769648ef5b394f69fdec2573a1403b789146be0c4217a443 12 | 13 | PKG_BUILD_DEPENDS:=golang/host homebox/host 14 | PKG_BUILD_PARALLEL:=1 15 | PKG_USE_MIPS16:=0 16 | 17 | HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME} 18 | 19 | include $(INCLUDE_DIR)/host-build.mk 20 | include $(INCLUDE_DIR)/package.mk 21 | include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk 22 | 23 | define Package/$(PKG_NAME) 24 | SECTION:=net 25 | CATEGORY:=Network 26 | SUBMENU:=Web Servers/Proxies 27 | TITLE:=A Toolbox for Home Local Networks 28 | URL:=https://github.com/XGHeaven/homebox 29 | DEPENDS:=$(GO_ARCH_DEPENDS) 30 | MENU:=1 31 | endef 32 | 33 | define Package/$(PKG_NAME)/description 34 | A Toolbox for Home Local Networks Speed Test 35 | endef 36 | 37 | GO_PKG_BUILD_VARS += GO111MODULE=auto 38 | TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS) 39 | TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS) 40 | 41 | define Build/Configure 42 | ( \ 43 | cd $(PKG_BUILD_DIR)/server; \ 44 | $(GO_PKG_VARS) \ 45 | go get -d -modcacherw; \ 46 | ) 47 | ( \ 48 | cd $(PKG_BUILD_DIR)/server; \ 49 | GOPATH=$(PKG_BUILD_DIR)/.go_work/build \ 50 | go install -modcacherw github.com/go-bindata/go-bindata/...@latest; \ 51 | ) 52 | endef 53 | 54 | define Build/Compile 55 | rm -rf $(PKG_BUILD_DIR)/build/static 56 | mkdir -p $(PKG_BUILD_DIR)/build 57 | $(CP) $(HOST_BUILD_DIR)/build/static $(PKG_BUILD_DIR)/build/ 58 | ( \ 59 | cd $(PKG_BUILD_DIR); \ 60 | $(GO_PKG_VARS) PATH=$(PKG_BUILD_DIR)/.go_work/build/bin:$$$$PATH \ 61 | $(MAKE) build-server; \ 62 | ) 63 | endef 64 | 65 | define Package/$(PKG_NAME)/install 66 | $(INSTALL_DIR) $(1)/usr/bin $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults 67 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/server $(1)/usr/bin/homebox 68 | $(INSTALL_CONF) ./files/homebox.config $(1)/etc/config/homebox 69 | $(INSTALL_BIN) ./files/homebox.init $(1)/etc/init.d/homebox 70 | $(INSTALL_BIN) ./files/homebox.uci-default $(1)/etc/uci-defaults/homebox 71 | endef 72 | 73 | define Package/$(PKG_NAME)/conffiles 74 | /etc/config/homebox 75 | endef 76 | 77 | define Package/$(PKG_NAME)/postinst 78 | #!/bin/sh 79 | if [ -z "$${IPKG_INSTROOT}" ]; then 80 | [ -f /etc/uci-defaults/homebox ] && /etc/uci-defaults/homebox && rm -f /etc/uci-defaults/homebox 81 | exit 0 82 | fi 83 | endef 84 | 85 | define Host/Configure 86 | cd $(HOST_BUILD_DIR)/web && rm -f package-lock.json && npm --cache-min 1440 install 87 | endef 88 | 89 | define Host/Compile 90 | cd $(HOST_BUILD_DIR) && $(MAKE) build-web 91 | endef 92 | 93 | define Host/Install 94 | endef 95 | 96 | define Host/Clean 97 | rm -f $(HOST_BUILD_DIR)/build/static 98 | endef 99 | 100 | $(eval $(call HostBuild)) 101 | $(eval $(call BuildPackage,homebox)) 102 | -------------------------------------------------------------------------------- /luci-app-cpufreq/po/templates/cpufreq.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | msgid "Tuning" 5 | msgstr "" 6 | 7 | msgid "CPU Tuning" 8 | msgstr "" 9 | 10 | msgid "Manage CPU performance over LuCI." 11 | msgstr "" 12 | 13 | msgid "CPU frequence:" 14 | msgstr "" 15 | 16 | msgid "temperature:" 17 | msgstr "" 18 | 19 | msgid "CPUFreq governor" 20 | msgstr "" 21 | 22 | msgid "Default (Take effect after reboot)" 23 | msgstr "" 24 | 25 | msgid "conservative" 26 | msgstr "" 27 | 28 | msgid "userspace" 29 | msgstr "" 30 | 31 | msgid "powersave" 32 | msgstr "" 33 | 34 | msgid "ondemand" 35 | msgstr "" 36 | 37 | msgid "performance" 38 | msgstr "" 39 | 40 | msgid "interactive" 41 | msgstr "" 42 | 43 | msgid "schedutil" 44 | msgstr "" 45 | 46 | msgid "It is recommended to use 'ondemand' or 'schedutil'" 47 | msgstr "" 48 | 49 | msgid "Frequency" 50 | msgstr "" 51 | 52 | msgid "Pay attention to heat dissipation when choosing high frequency" 53 | msgstr "" 54 | 55 | msgid "Fan trigger temperature" 56 | msgstr "" 57 | 58 | msgid "Fan temperature hysteresis" 59 | msgstr "" 60 | 61 | msgid "Set a larger value to avoid frequent restart of the fan" 62 | msgstr "" 63 | 64 | msgid "IPK Mirror" 65 | msgstr "" 66 | 67 | msgid "Select IPK Mirror server" 68 | msgstr "" 69 | 70 | msgid "Mirror server" 71 | msgstr "" 72 | 73 | msgid "Tsinghua University" 74 | msgstr "" 75 | 76 | msgid "USTC" 77 | msgstr "" 78 | 79 | msgid "Alibaba Cloud" 80 | msgstr "" 81 | 82 | msgid "Tencent Cloud" 83 | msgstr "" 84 | 85 | msgid "Boot" 86 | msgstr "" 87 | 88 | msgid "Delay before mounting" 89 | msgstr "" 90 | 91 | msgid "Timeout (seconds)" 92 | msgstr "" 93 | 94 | msgid "Or until these device(s) ready (UUID):" 95 | msgstr "" 96 | 97 | msgid "Samba expert" 98 | msgstr "" 99 | 100 | msgid "Allow legacy protocols" 101 | msgstr "" 102 | 103 | msgid "Allow old client, don't use this option for secure environments!" 104 | msgstr "" 105 | 106 | msgid "Sandbox" 107 | msgstr "" 108 | 109 | msgid "Simple sandbox for OpenWRT" 110 | msgstr "" 111 | 112 | msgid "This action will reboot device" 113 | msgstr "" 114 | 115 | msgid "Commit" 116 | msgstr "" 117 | 118 | msgid "Reset" 119 | msgstr "" 120 | 121 | msgid "cpufreq/sb_info" 122 | msgstr "" 123 | 124 | msgid "cpufreq/sb_guide" 125 | msgstr "" 126 | 127 | msgid "Network" 128 | msgstr "" 129 | 130 | msgid "Hardware Acceleration" 131 | msgstr "" 132 | 133 | msgid "Enable PPPoE Acceleration" 134 | msgstr "" 135 | 136 | msgid "Improve PPPoE TX performace, only support built-in NICs" 137 | msgstr "" 138 | 139 | msgid "Exit Sandbox" 140 | msgstr "" 141 | 142 | msgid "Enable WAN Port Acceleration" 143 | msgstr "" 144 | 145 | msgid "Improve built-in WAN port (eth0) TX performace" 146 | msgstr "" 147 | 148 | msgid "Drivers" 149 | msgstr "" 150 | 151 | msgid "Drivers Settings" 152 | msgstr "" 153 | 154 | msgid "Realtek r8125 driver" 155 | msgstr "" 156 | 157 | msgid "Realtek r8168 driver" 158 | msgstr "" 159 | 160 | msgid "Backported Intel GPU driver (i915-oot)" 161 | msgstr "" 162 | 163 | msgid "Enable additional drivers" 164 | msgstr "" 165 | 166 | msgid "Configure device drivers, kernel modules, etc. Changes here will take effect on next boot" 167 | msgstr "" 168 | 169 | msgid "Please do not choose a driver you do not understand. Choosing the wrong driver may cause the system to fail to start" 170 | msgstr "" 171 | -------------------------------------------------------------------------------- /luci-app-fan/luasrc/model/cbi/luci-fan.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2023 jjm2473 4 | ]]-- 5 | 6 | local m, s, o 7 | require "luci.util" 8 | 9 | local fs = require "nixio.fs" 10 | 11 | local sys = require "luci.sys" 12 | 13 | local words = luci.util.split(luci.util.trim(sys.exec("/usr/libexec/fan-control get 2>/dev/null")), " ") 14 | 15 | if #words < 3 then 16 | return 17 | end 18 | 19 | m = Map("luci-fan", translate("Fan Control"), translate("Control fan start and stop temperature. This plugin can only configure the lowest gear, not necessarily applicable to all devices.")) 20 | 21 | s = m:section(SimpleSection) 22 | s.template = "luci-fan" 23 | s.thermal_zone = words[1] 24 | s.trip_point = words[2] 25 | s.thermal_type = luci.util.trim(fs.readfile("/sys/class/thermal/"..words[1].."/type")) 26 | 27 | s = m:section(TypedSection, "luci-fan", translate("Fan Settings")) 28 | s.addremove = false 29 | s.anonymous = true 30 | 31 | o = s:option(Flag, "enabled", translate("Enabled"), translate("Whether to apply the settings")) 32 | o.default = 0 33 | 34 | local on_temp = s:option(Value, "on_temp", translate("Fan start temperature") .. " (℃)") 35 | on_temp.datatype = "and(uinteger,min(5))" 36 | on_temp.rmempty = false 37 | on_temp.default = math.floor(tonumber(words[3])/1000) 38 | if #words > 3 then 39 | on_temp.datatype = string.format("and(uinteger,range(5,%u))", math.floor(tonumber(words[4])/1000 - 1)) 40 | end 41 | 42 | o = s:option(Value, "off_temp", translate("Fan stop temperature") .. " (℃)", translate("Optional, MUST be lower than the fan start temperature. Default fan start temperature minus 5 ℃")) 43 | o.datatype = "uinteger" 44 | o.rmempty = true 45 | function o.parse(self, section, novld) 46 | local fvalue = self:formvalue(section) 47 | local fexist = ( fvalue and (#fvalue > 0) ) -- not "nil" and "not empty" 48 | 49 | local vvalue, errtxt = self:validate(fvalue) 50 | if not vvalue then 51 | if novld then -- and "novld" set 52 | return -- then exit without raising an error 53 | end 54 | if fexist then -- and there is a formvalue 55 | self:add_error(section, "invalid", errtxt or self.title .. ": invalid") 56 | return -- so data are invalid 57 | end 58 | end 59 | local rm_opt = ( self.rmempty or self.optional ) 60 | local vexist = ( vvalue and (#vvalue > 0) ) and true or false -- not "nil" and "not empty" 61 | local eq_def = ( vvalue == self.default ) -- equal_default flag 62 | -- (rmempty or optional) and (no data or equal_default) 63 | if rm_opt and (not vexist or eq_def) then 64 | if self:remove(section) then -- remove data from UCI 65 | self.section.changed = true -- and push events 66 | end 67 | return 68 | end 69 | 70 | local cvalue = self:cfgvalue(section) 71 | local eq_cfg = ( vvalue == cvalue ) -- update equal_config flag 72 | -- not forcewrite and no changes, so nothing to write 73 | if not self.forcewrite and eq_cfg then 74 | return 75 | end 76 | 77 | local onvalue = on_temp:validate(on_temp:formvalue(section)) 78 | if onvalue and #onvalue > 0 then 79 | if tonumber(vvalue) >= tonumber(onvalue) then 80 | self:add_error(section, "invalid", translate("Fan stop temperature MUST be lower than fan start temperature")) 81 | return 82 | end 83 | else 84 | return 85 | end 86 | 87 | -- write data to UCI; raise event only on changes 88 | if self:write(section, vvalue) and not eq_cfg then 89 | self.section.changed = true 90 | end 91 | end 92 | 93 | return m 94 | -------------------------------------------------------------------------------- /luci-app-cpufreq/luasrc/controller/admin/cpufreq.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | Copyright 2021 jjm2473 4 | ]]-- 5 | 6 | module("luci.controller.admin.cpufreq",package.seeall) 7 | require "luci.util" 8 | 9 | function index() 10 | local sys = require "luci.sys" 11 | local appname = "tuning" 12 | local defaultpage = nil 13 | entry({"admin", "system", appname}).dependent = true 14 | if nixio.fs.access("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq") then 15 | defaultpage = defaultpage or alias("admin", "system", appname, "main") 16 | entry({"admin", "system", appname, "main"}, cbi("cpufreq/main"), _("CPU Tuning"), 1).leaf = true 17 | entry({"admin", "system", appname, "get_cpu_info"}, call("get_cpu_info"), nil).leaf = true 18 | end 19 | if nixio.fs.access("/rom/etc/opkg/distfeeds.conf") then 20 | defaultpage = defaultpage or alias("admin", "system", appname, "ipk") 21 | entry({"admin", "system", appname, "ipk"}, cbi("cpufreq/ipk"), _("IPK Mirror"), 2).leaf = true 22 | end 23 | if nixio.fs.access("/etc/config/samba4") then 24 | defaultpage = defaultpage or alias("admin", "system", appname, "samba") 25 | entry({"admin", "system", appname, "samba"}, cbi("cpufreq/samba"), _("Samba"), 3).leaf = true 26 | end 27 | defaultpage = defaultpage or alias("admin", "system", appname, "boot") 28 | entry({"admin", "system", appname, "boot"}, cbi("cpufreq/boot"), _("Boot"), 4).leaf = true 29 | 30 | if nixio.fs.access("/etc/config/kmods") and sys.call("[ -n \"$(ls /etc/modules-pending.d/ 2>/dev/null | head -c1)\" ] >/dev/null 2>&1") == 0 then 31 | entry({"admin", "system", appname, "kmods"}, cbi("cpufreq/kmods"), _("Drivers"), 5).leaf = true 32 | end 33 | 34 | if sys.call("[ -d /ext_overlay ] >/dev/null 2>&1") == 0 then 35 | entry({"admin", "system", appname, "sandbox"}, call("sandbox_index", 36 | {prefix=luci.dispatcher.build_url("admin", "system", appname, "sandbox")}), _("Sandbox"), 6) 37 | entry({"admin", "system", appname, "sandbox", "reset"}, post("sandbox_reset")) 38 | entry({"admin", "system", appname, "sandbox", "commit"}, post("sandbox_commit")) 39 | entry({"admin", "system", appname, "sandbox", "exit"}, post("sandbox_exit")) 40 | end 41 | 42 | local hwppoe_feature = luci.util.trim(sys.exec("ethtool -k eth0 2>/dev/null | grep -F hw-pppoe: 2>/dev/null")) 43 | if hwppoe_feature ~= nil and hwppoe_feature ~= "" and not string.match(hwppoe_feature, "%[fixed%]") then 44 | entry({"admin", "system", appname, "net"}, cbi("cpufreq/net"), _("Network"), 7).leaf = true 45 | end 46 | 47 | if nixio.fs.access("/etc/init.d/grub") then 48 | entry({"admin", "system", appname, "cmdline"}, cbi("cpufreq/cmdline"), _("Kernel Cmdline"), 8).leaf = true 49 | end 50 | 51 | if defaultpage then 52 | entry({"admin", "system", appname}, defaultpage, _("Tuning"), 59) 53 | end 54 | 55 | end 56 | 57 | function get_cpu_info() 58 | local fs = require "nixio.fs" 59 | local freq = tonumber(fs.readfile("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq")) / 1000; -- MHz 60 | luci.http.status(200, "ok") 61 | luci.http.prepare_content("application/json") 62 | luci.http.write_json({freq=freq}) 63 | end 64 | 65 | function sandbox_index(param) 66 | luci.template.render("cpufreq/sandbox", {prefix=param.prefix}) 67 | end 68 | 69 | function sandbox_reset() 70 | local sys = require "luci.sys" 71 | sys.call("/usr/sbin/sandbox reset") 72 | luci.sys.reboot() 73 | end 74 | 75 | function sandbox_commit() 76 | local sys = require "luci.sys" 77 | sys.call("/usr/sbin/sandbox commit") 78 | luci.sys.reboot() 79 | end 80 | 81 | function sandbox_exit() 82 | local sys = require "luci.sys" 83 | sys.call("/usr/sbin/sandbox exit") 84 | luci.sys.reboot() 85 | end 86 | -------------------------------------------------------------------------------- /luci-app-mergerfs/po/zh_Hans/mergerfs.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Language: zh_Hans\n" 4 | "Content-Type: text/plain; charset=UTF-8\n" 5 | "Content-Transfer-Encoding: 8bit\n" 6 | "Plural-Forms: nplurals=1; plural=0;\n" 7 | 8 | msgid "Create policy" 9 | msgstr "创建策略" 10 | 11 | msgid "Each line must be a path starting with a '/' or be a comment starting with '#'." 12 | msgstr "每行必须是以'/'开头的路径或者以'#'开头的注释。" 13 | 14 | msgid "Existing path - all" 15 | msgstr "现有路径 - 全部" 16 | 17 | msgid "Existing path - first found" 18 | msgstr "现有路径 - 第一个找到的" 19 | 20 | msgid "Existing path - least free space" 21 | msgstr "现有路径 - 最少可用空间" 22 | 23 | msgid "Existing path - least used space" 24 | msgstr "现有路径 - 最少已用空间" 25 | 26 | msgid "Existing path - most free space" 27 | msgstr "现有路径 - 最多可用空间" 28 | 29 | msgid "Existing path - percentage free random distribution" 30 | msgstr "现有路径 - 按可用空间百分比随机分布" 31 | 32 | msgid "Existing path - random" 33 | msgstr "现有路径 - 随机" 34 | 35 | msgid "Failed to unmount" 36 | msgstr "卸载失败" 37 | 38 | msgid "First found" 39 | msgstr "第一个找到的" 40 | 41 | msgid "If mounting fails, search \"mergerfs\" in the system log for more information." 42 | msgstr "如果挂载失败,在系统日志中搜索\"mergerfs\"以获取信息。" 43 | 44 | msgid "Least free space" 45 | msgstr "最少可用空间" 46 | 47 | msgid "Least used space" 48 | msgstr "最少已用空间" 49 | 50 | msgid "List of paths to merge, one per line. Line starting with '#' will be treated as a comment.
All paths must existed before mounting or the mounting will fail." 51 | msgstr "要合并的路径列表,每行一个路径。以'#'开头的行将被视为注释。
挂载前所有路径必须存在,否则挂载将失败。" 52 | 53 | msgid "MergerFS Pool" 54 | msgstr "MergerFS 存储池" 55 | 56 | msgid "MergerFS is a union filesystem, which allows you to pool multiple directories into a single mount point.
This is useful for combining storage space and files from multiple devices or directories into one accessible location.
New files can be distributed across the pooled directories based on various policies, such as most free space or first found.
More information can be found at GitHub." 57 | msgstr "MergerFS 是一个联合文件系统,允许您将多个目录池化到一个挂载点。
这对于将来自多个设备或目录的存储空间和文件合并到一个可访问的位置很有用。
新文件可以根据各种策略(如最多可用空间或第一个找到的)分布在池化的目录中。
更多信息可以在 GitHub 找到。" 58 | 59 | msgid "Minimum free space" 60 | msgstr "最小可用空间" 61 | 62 | msgid "Most free space" 63 | msgstr "最多可用空间" 64 | 65 | msgid "Most shared path - least free space" 66 | msgstr "最多共享路径 - 最少可用空间" 67 | 68 | msgid "Most shared path - least used space" 69 | msgstr "最多共享路径 - 最少已用空间" 70 | 71 | msgid "Most shared path - most free space" 72 | msgstr "最多共享路径 - 最多可用空间" 73 | 74 | msgid "Most shared path - percentage free random distribution" 75 | msgstr "最多共享路径 - 按可用空间百分比随机分布" 76 | 77 | msgid "Mount Configured MergerFS" 78 | msgstr "挂载已配置的 MergerFS" 79 | 80 | msgid "Mount to this path" 81 | msgstr "挂载到此路径" 82 | 83 | msgid "Mounted MergerFS" 84 | msgstr "已挂载的 MergerFS" 85 | 86 | msgid "No mounted MergerFS found" 87 | msgstr "未找到已挂载的 MergerFS" 88 | 89 | msgid "Mount Point is required, must start with \"/\" and cannot be root \"/\"" 90 | msgstr "挂载点是必需的,必须以\"/\"开头且不能是根目录\"/\"" 91 | 92 | msgid "Newest file" 93 | msgstr "最新文件" 94 | 95 | msgid "Options" 96 | msgstr "选项" 97 | 98 | msgid "Paths" 99 | msgstr "路径" 100 | 101 | msgid "Percentage free random distribution" 102 | msgstr "按可用空间百分比随机分布" 103 | 104 | msgid "Please enter a value like 4G, 500M, 100K" 105 | msgstr "请输入类似 4G, 500M, 100K 的值" 106 | 107 | msgid "Policy for creating new files" 108 | msgstr "创建新文件的策略" 109 | 110 | msgid "Pool Settings" 111 | msgstr "存储池设置" 112 | 113 | msgid "Put each folder on a new line." 114 | msgstr "每行放一个文件夹。" 115 | 116 | msgid "Random" 117 | msgstr "随机" 118 | 119 | msgid "Read-only" 120 | msgstr "只读" 121 | 122 | msgid "You must provide at least one valid path (not a comment or empty line)." 123 | msgstr "您必须提供至少一个有效路径(不是注释或空行)。" 124 | -------------------------------------------------------------------------------- /luci-app-fan/root/usr/libexec/fan-control: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # author: jjm2473 3 | 4 | SAVE=/tmp/run/fanTP 5 | ACTION=${1} 6 | shift 7 | 8 | # print: zone trip_point current_target_temp [max_target_temp] 9 | # ex. thermal_zone0 0 50000 60000 10 | function getFanTP() { 11 | local zone cdev trip temp mintemp mintrip minzone maxtemp 12 | [[ -d /sys/class/thermal ]] || return 1 13 | cd /sys/class/thermal 14 | for zone in thermal_zone* ; do 15 | cd "$zone" 16 | for cdev in `ls | grep 'cdev[0-9]\+$'`; do 17 | [[ -d "$cdev" ]] || continue 18 | grep -Fiq fan "$cdev/type" || continue 19 | trip=`cat ${cdev}_trip_point` 20 | grep -Fwq active trip_point_${trip}_type || continue 21 | [[ "`stat -c '%#a' trip_point_${trip}_temp || echo 0444`" = "0644" ]] || continue 22 | temp=`cat trip_point_${trip}_temp` 23 | if [[ -z "$mintemp" ]] || [[ "$temp" -lt "$mintemp" ]]; then 24 | if [[ -n "$mintemp" ]]; then 25 | if [[ "$zone" = "$minzone" ]]; then 26 | maxtemp=$mintemp 27 | else 28 | maxtemp= 29 | fi 30 | fi 31 | mintemp=$temp 32 | mintrip=$trip 33 | minzone=$zone 34 | elif [[ -z "$maxtemp" ]] || [[ "$temp" -lt "$maxtemp" ]]; then 35 | maxtemp=$temp 36 | fi 37 | done 38 | cd /sys/class/thermal 39 | done 40 | if [[ -n "$mintemp" ]]; then 41 | echo "$minzone" "$mintrip" "$mintemp" $maxtemp 42 | return 0 43 | else 44 | return 1 45 | fi 46 | } 47 | 48 | function getFanTP_C() { 49 | if [[ -f "$SAVE" ]]; then 50 | if [[ -s "$SAVE" ]]; then 51 | cat "$SAVE" 52 | return 0 53 | else 54 | return 1 55 | fi 56 | fi 57 | ( getFanTP ) | tee "$SAVE" 58 | [[ -s "$SAVE" ]] 59 | } 60 | 61 | function getFanTP_U() { 62 | set $(getFanTP_C) 63 | [[ -n "$1" && -n "$2" ]] || return 1 64 | local onTemp=`cat "/sys/class/thermal/${1}/trip_point_${2}_temp"` 65 | echo "$1" "$2" "$onTemp" $4 66 | return 0 67 | } 68 | 69 | function initFanTP() { 70 | [[ -f "$SAVE" ]] || ( getFanTP >"$SAVE" ) 71 | } 72 | 73 | # param: ON_TEMP [OFF_TEMP] 74 | # OFF_TEMP = ON_TEMP - 5000 if not set 75 | # ex. 60000 55000 76 | function setFanTP() { 77 | local ON_TEMP=$1 78 | local OFF_TEMP=$2 79 | [[ -n "$ON_TEMP" ]] || { 80 | echo "ON_TEMP must be present" >&2 81 | return 1 82 | } 83 | if [[ -z "$OFF_TEMP" ]]; then 84 | [[ "$ON_TEMP" -gt 5000 ]] || { 85 | echo "ON_TEMP must greater than 5000 when OFF_TEMP not present" >&2 86 | return 1 87 | } 88 | OFF_TEMP=$(( $ON_TEMP - 5000 )) 89 | fi 90 | [[ "$ON_TEMP" -gt "$OFF_TEMP" ]] || { 91 | echo "ON_TEMP must greater than OFF_TEMP" >&2 92 | return 1 93 | } 94 | local HYST=$(( $ON_TEMP - $OFF_TEMP )) 95 | 96 | set $(getFanTP_C) 97 | [[ -n "$1" && -n "$2" ]] || return 1 98 | [[ -d "/sys/class/thermal/${1}" ]] || return 1 99 | 100 | [[ -n "$4" ]] && [[ "$ON_TEMP" -ge "$4" ]] && { 101 | ON_TEMP=$(( $4 - 5000 )) 102 | echo "WARN: ON_TEMP greater than next TP $4, fixed to $ON_TEMP" >&2 103 | } 104 | echo "$ON_TEMP" > "/sys/class/thermal/${1}/trip_point_${2}_temp" 105 | echo "$HYST" > "/sys/class/thermal/${1}/trip_point_${2}_hyst" 106 | } 107 | 108 | # print: current thermal sensor value and fan on temp 109 | function getTemp() { 110 | set $(getFanTP_C) 111 | [[ -n "$1" && -n "$2" ]] || return 1 112 | [[ -f "/sys/class/thermal/$1/temp" ]] || return 1 113 | local temp=`cat "/sys/class/thermal/$1/temp"` 114 | local tpt=`cat "/sys/class/thermal/$1/trip_point_${2}_temp"` 115 | echo "$temp $tpt" 116 | } 117 | 118 | usage() { 119 | echo "usage: $0 sub-command" 120 | echo "where sub-command is one of:" 121 | echo " get Get Fan setting" 122 | echo " set ON_TEMP [OFF_TEMP] Set Fan setting" 123 | echo " temp Get current thermal temp and Fan on temp" 124 | echo " init init, internal used" 125 | } 126 | 127 | case ${ACTION} in 128 | "get") 129 | getFanTP_U 130 | ;; 131 | "set") 132 | setFanTP "$@" 133 | ;; 134 | "temp") 135 | getTemp 136 | ;; 137 | "init") 138 | initFanTP 139 | ;; 140 | *) 141 | usage 142 | exit 1 143 | ;; 144 | esac 145 | 146 | -------------------------------------------------------------------------------- /luci-app-cpufreq/po/zh-cn/cpufreq.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | msgid "Tuning" 5 | msgstr "杂项设置" 6 | 7 | msgid "CPU Tuning" 8 | msgstr "CPU调节" 9 | 10 | msgid "Manage CPU performance over LuCI." 11 | msgstr "通过LuCI调节CPU性能" 12 | 13 | msgid "CPU frequence:" 14 | msgstr "CPU频率:" 15 | 16 | msgid "temperature:" 17 | msgstr "核心温度:" 18 | 19 | msgid "CPUFreq governor" 20 | msgstr "CPU性能策略" 21 | 22 | msgid "Apply" 23 | msgstr "应用" 24 | 25 | msgid "Default (Take effect after reboot)" 26 | msgstr "默认(重启后生效)" 27 | 28 | msgid "conservative" 29 | msgstr "Conservative(平滑)" 30 | 31 | msgid "userspace" 32 | msgstr "手动/固定频率" 33 | 34 | msgid "powersave" 35 | msgstr "节能模式" 36 | 37 | msgid "ondemand" 38 | msgstr "自动调节" 39 | 40 | msgid "performance" 41 | msgstr "性能模式" 42 | 43 | msgid "interactive" 44 | msgstr "Interactive(灵敏)" 45 | 46 | msgid "schedutil" 47 | msgstr "基于调度器" 48 | 49 | msgid "It is recommended to use 'ondemand' or 'schedutil'" 50 | msgstr "推荐使用“自动调节”或“基于调度器”" 51 | 52 | msgid "Frequency" 53 | msgstr "频率" 54 | 55 | msgid "Pay attention to heat dissipation when choosing high frequency" 56 | msgstr "选择高频时注意散热" 57 | 58 | msgid "Fan trigger temperature" 59 | msgstr "风扇启动温度" 60 | 61 | msgid "Fan temperature hysteresis" 62 | msgstr "风扇温度容错" 63 | 64 | msgid "Set a larger value to avoid frequent restart of the fan" 65 | msgstr "设置更大的值以避免频繁重启风扇" 66 | 67 | msgid "IPK Mirror" 68 | msgstr "IPK镜像服务器" 69 | 70 | msgid "Select IPK Mirror server" 71 | msgstr "选择IPK镜像服务器" 72 | 73 | msgid "Mirror server" 74 | msgstr "镜像服务器" 75 | 76 | msgid "Tsinghua University" 77 | msgstr "清华大学" 78 | 79 | msgid "USTC" 80 | msgstr "中国科学技术大学" 81 | 82 | msgid "Alibaba Cloud" 83 | msgstr "阿里云" 84 | 85 | msgid "Tencent Cloud" 86 | msgstr "腾讯云" 87 | 88 | msgid "CERNET 302" 89 | msgstr "高校联合镜像站(智能选择最近大学镜像站)" 90 | 91 | msgid "SUSTech" 92 | msgstr "南方科技大学" 93 | 94 | msgid "Lanzhou University" 95 | msgstr "兰州大学" 96 | 97 | msgid "Chinese Academy of Sciences" 98 | msgstr "中国科学院" 99 | 100 | msgid "NYIST" 101 | msgstr "南洋理工大学" 102 | 103 | msgid "SJTU" 104 | msgstr "上海交通大学" 105 | 106 | msgid "CQUPT" 107 | msgstr "重庆邮电大学" 108 | 109 | msgid "Qilu University of Technology" 110 | msgstr "齐鲁工业大学" 111 | 112 | msgid "Boot" 113 | msgstr "启动" 114 | 115 | msgid "Delay before disk mounting" 116 | msgstr "挂载前等待磁盘" 117 | 118 | msgid "Wait for the hard disk to initialize to solve the problem that the hard disk is not mounted when some applications that rely on the hard disk are started." 119 | msgstr "等待硬盘初始化,以解决部分依赖硬盘的应用启动时硬盘还未挂载的问题" 120 | 121 | msgid "Do not select a network block device (e.g. NBD, iSCSI, etc.), you may have to wait until timeout." 122 | msgstr "请勿选择网络块设备(例如 NBD,iSCSI 等),可能必须等到超时" 123 | 124 | msgid "Timeout (seconds)" 125 | msgstr "超时(秒)" 126 | 127 | msgid "Or until these device(s) ready (UUID):" 128 | msgstr "或者直到这些磁盘准备好(UUID):" 129 | 130 | msgid "Samba expert" 131 | msgstr "Samba高级设置" 132 | 133 | msgid "Allow legacy protocols" 134 | msgstr "允许旧协议" 135 | 136 | msgid "Allow old client, don't use this option for secure environments!" 137 | msgstr "允许老客户端连接(例如一些电视盒或手机),可能有安全风险" 138 | 139 | msgid "Sandbox" 140 | msgstr "沙箱" 141 | 142 | msgid "Simple sandbox for OpenWRT" 143 | msgstr "一个简易沙箱" 144 | 145 | msgid "This action will reboot device" 146 | msgstr "此操作将重启设备" 147 | 148 | msgid "Commit" 149 | msgstr "提交" 150 | 151 | msgid "Reset" 152 | msgstr "重置" 153 | 154 | msgid "cpufreq/sb_info" 155 | msgstr "cpufreq/sb_info.zh-cn" 156 | 157 | msgid "cpufreq/sb_guide" 158 | msgstr "cpufreq/sb_guide.zh-cn" 159 | 160 | msgid "Network" 161 | msgstr "网络" 162 | 163 | msgid "Hardware Acceleration" 164 | msgstr "硬件加速" 165 | 166 | msgid "Enable PPPoE Acceleration" 167 | msgstr "启用PPPoE加速" 168 | 169 | msgid "Improve PPPoE TX performace, only support built-in NICs" 170 | msgstr "提升PPPoE发送(TX)性能,只支持内置网卡" 171 | 172 | msgid "Exit Sandbox" 173 | msgstr "退出沙箱" 174 | 175 | msgid "Enable WAN Port Acceleration" 176 | msgstr "启用WAN口加速" 177 | 178 | msgid "Improve built-in WAN port (eth0) TX performace" 179 | msgstr "提升WAN口(eth0)发送(TX)性能" 180 | 181 | msgid "Drivers" 182 | msgstr "驱动" 183 | 184 | msgid "Drivers Settings" 185 | msgstr "驱动设置" 186 | 187 | msgid "Realtek r8125 driver" 188 | msgstr "Realtek r8125 驱动" 189 | 190 | msgid "Realtek r8168 driver" 191 | msgstr "Realtek r8168 驱动" 192 | 193 | msgid "Backported Intel GPU driver (i915-oot)" 194 | msgstr "移植 Intel GPU 驱动 (i915-oot)" 195 | 196 | msgid "Enable additional drivers" 197 | msgstr "启用额外的驱动" 198 | 199 | msgid "Configure device drivers, kernel modules, etc. Changes here will take effect on next boot" 200 | msgstr "配置设备驱动程序,内核模块等。这里的变更将在下次启动时生效" 201 | 202 | msgid "Please do not choose a driver you do not understand. Choosing the wrong driver may cause the system to fail to start" 203 | msgstr "请勿选择不了解的驱动程序,选择错误可能导致系统无法启动" 204 | 205 | msgid "Kernel Cmdline" 206 | msgstr "内核启动参数" 207 | 208 | msgid "Current Cmdline" 209 | msgstr "当前内核启动参数" 210 | 211 | msgid "This page configures Linux kernel boot parameters. After saving and applying, the GRUB configuration file of the boot partition will be modified. The parameters will take effect after restarting the system (the boot partition is not within the scope of sandbox protection, please be aware)" 212 | msgstr "此页面可配置 Linux 内核启动参数。保存并应用以后将修改 boot 分区的 GRUB 配置文件,重启系统以后参数生效(boot分区不在沙箱保护范围,请知悉)" 213 | 214 | msgid "Supports PCI device passthrough for virtual machines (KVM/QEMU)" 215 | msgstr "用于支持虚拟机(KVM/QEMU)的 PCI 设备直通" 216 | 217 | msgid "Parameters" 218 | msgstr "参数" 219 | 220 | msgid "Default" 221 | msgstr "默认" 222 | 223 | msgid "Default or empty will be automatically filled in according to the current platform" 224 | msgstr "默认或者空将自动按当前平台填写" 225 | 226 | msgid "Custom Parameters" 227 | msgstr "自定义内核参数" 228 | 229 | msgid "Danger! If you do not understand the kernel boot parameters, do not modify them to avoid being unable to start or damaging the hardware" 230 | msgstr "前方危险!如果不了解内核启动参数,请勿修改,以免无法启动或损坏硬件" 231 | -------------------------------------------------------------------------------- /luci-app-mergerfs/htdocs/luci-static/resources/view/mergerfs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require fs'; 4 | 'require ui'; 5 | 'require uci'; 6 | 'require rpc'; 7 | 'require form'; 8 | 9 | var callMountPoints = function(){ 10 | return (rpc.declare({ 11 | object: 'luci', 12 | method: 'getMountPoints', 13 | expect: { result: [] } 14 | }))().then(function(mounts) { 15 | // Filter out mounts that are not managed by mergerfs 16 | return (mounts || []).filter(function(mount) { 17 | return mount.device && mount.device.startsWith('mergerfs:/'); 18 | }); 19 | }); 20 | }; 21 | 22 | return view.extend({ 23 | 24 | handleUmount: function(m, mounts, i, ev) { 25 | return fs.exec('/bin/umount', [mounts[i].mount]) 26 | .then(function(res){ 27 | if (res.code === 0) 28 | mounts.splice(i, 1); 29 | else 30 | throw new Error(res.stderr || res.message || _('Failed to unmount')); 31 | }) 32 | .then(L.bind(m.render, m)) 33 | .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); 34 | }, 35 | 36 | handleReload: function(m, mounts, ev) { 37 | return fs.exec('/etc/init.d/mergerfs', ['reload']) 38 | .then(()=> 39 | new Promise(function(resolve) { 40 | setTimeout(resolve, 200); 41 | }) 42 | ) 43 | .then(callMountPoints) 44 | .then(function(newMounts) { 45 | if (newMounts && newMounts.length > 0) { 46 | mounts.splice(0, mounts.length, ...newMounts); 47 | } else { 48 | mounts.length = 0; // Clear the mounts if no new ones found 49 | } 50 | }) 51 | .then(L.bind(m.render, m)) 52 | .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); 53 | }, 54 | 55 | load: function() { 56 | return Promise.all([ 57 | callMountPoints(), 58 | ]); 59 | }, 60 | 61 | render: function(data) { 62 | var m, s, o; 63 | m = new form.Map('mergerfs', _('MergerFS Pool'), _('MergerFS is a union filesystem, which allows you to pool multiple directories into a single mount point.
This is useful for combining storage space and files from multiple devices or directories into one accessible location.
New files can be distributed across the pooled directories based on various policies, such as most free space or first found.
More information can be found at GitHub.')); 64 | 65 | var mounts = data[0]||[]; 66 | 67 | // Mount status table 68 | s = m.section(form.GridSection, '_mtab'); 69 | 70 | s.render = L.bind(function(view, section_id) { 71 | var desc = E('div', { 'class': 'cbi-section-descr' }, 72 | _('If mounting fails, search "mergerfs" in the system log for more information.') 73 | ); 74 | var reload = E('div', { 'class': 'cbi-section-node' }, [ 75 | E('button', { 76 | 'class': 'btn cbi-button-reload', 77 | 'click': ui.createHandlerFn(view, 'handleReload', m, mounts), 78 | }, [ _('Mount Configured MergerFS') ]) 79 | ]); 80 | var table = E('table', { 'class': 'table cbi-section-table' }, [ 81 | E('tr', { 'class': 'tr table-titles' }, [ 82 | E('th', { 'class': 'th' }, _('Mount Point')), 83 | E('th', { 'class': 'th center' }, _('Available')), 84 | E('th', { 'class': 'th center' }, _('Used')), 85 | E('th', { 'class': 'th' }, _('Unmount')) 86 | ]) 87 | ]); 88 | 89 | var rows = []; 90 | 91 | for (var i = 0; i < mounts.length; i++) { 92 | var used = mounts[i].size - mounts[i].free, 93 | umount = true; 94 | 95 | if (/^\/(overlay|rom|tmp(?:\/.+)?|dev(?:\/.+)?|)$/.test(mounts[i].mount)) 96 | umount = false; 97 | 98 | rows.push([ 99 | mounts[i].mount, 100 | '%1024.2mB / %1024.2mB'.format(mounts[i].avail, mounts[i].size), 101 | '%.2f%% (%1024.2mB)'.format(100 / mounts[i].size * used, used), 102 | umount ? E('button', { 103 | 'class': 'btn cbi-button-remove', 104 | 'click': ui.createHandlerFn(view, 'handleUmount', m, mounts, i), 105 | 'disabled': this.map.readonly || null 106 | }, [ _('Unmount') ]) : '-' 107 | ]); 108 | } 109 | 110 | cbi_update_table(table, rows, E('em', _('No mounted MergerFS found'))); 111 | 112 | return E('div', { 'class': 'cbi-section cbi-tblsection' }, [ E('h3', _('Mounted MergerFS')), desc, reload, table ]); 113 | }, s, this); 114 | 115 | // 基本信息分区 116 | s = m.section(form.GridSection, 'pool', _('Pool Settings')); 117 | s.anonymous = true; 118 | s.addremove = true; 119 | 120 | o = s.option(form.Flag, 'enabled', _('Enabled')); 121 | o.rmempty = false; 122 | o.default = true; 123 | o.editable = true; 124 | 125 | // type: textInput, name: mountpoint 126 | o = s.option(form.Value, 'mountpoint', _('Mount Point'), _('Mount to this path')); 127 | o.datatype = 'string'; 128 | o.placeholder = '/mnt/mergerfs'; 129 | o.rmempty = false; 130 | // o.editable = true; 131 | o.validate = function(section_id, value) { 132 | value = value ? value.trim() : value; 133 | if (!value || !value.startsWith('/') || value === '/') { 134 | return _('Mount Point is required, must start with "/" and cannot be root "/"'); 135 | } 136 | return true; 137 | }; 138 | o.cfgvalue = function(section_id) { 139 | var v = uci.get('mergerfs', section_id, 'mountpoint'); 140 | return v ? v.trim() : v; 141 | }; 142 | o.write = function(section_id, formvalue) { 143 | return uci.set('mergerfs', section_id, 'mountpoint', formvalue ? formvalue.trim() : formvalue); 144 | }; 145 | 146 | var clean_paths = function(val) { 147 | if (!val || typeof val !== 'string') return val; 148 | return val.split('\n').map(function(line) { 149 | line = line.trim(); 150 | if (line.startsWith('#')) return line; 151 | if (line !== '/' && line.endsWith('/')) { 152 | return line.slice(0, -1); 153 | } 154 | return line; 155 | }).join('\n'); 156 | }; 157 | 158 | // type: textarea, name: paths 159 | o = s.option(form.TextValue, 'paths', _('Paths'), _("List of paths to merge, one per line. Line starting with '#' will be treated as a comment.
All paths must existed before mounting or the mounting will fail.")); 160 | o.datatype = 'string'; 161 | o.modalonly = true; 162 | o.rows = 5; 163 | o.placeholder = _('Put each folder on a new line.'); 164 | o.validate = function(section_id, value) { 165 | var paths = clean_paths(value).split('\n'); 166 | if (!paths.every(function(line) { return line.length === 0 || line.startsWith('/') || line.startsWith('#'); })) { 167 | return _("Each line must be a path starting with a '/' or be a comment starting with '#'."); 168 | } 169 | if (!paths.some(function(line) { return line && line.startsWith('/'); })) { 170 | return _('You must provide at least one valid path (not a comment or empty line).'); 171 | } 172 | return true; 173 | }; 174 | o.cfgvalue = function(section_id) { 175 | var v = uci.get('mergerfs', section_id, 'paths'); 176 | return clean_paths(v); 177 | }; 178 | o.write = function(section_id, formvalue) { 179 | return uci.set('mergerfs', section_id, 'paths', clean_paths(formvalue)); 180 | }; 181 | 182 | // type: select, name: createpolicy 183 | o = s.option(form.ListValue, 'createpolicy', _('Create policy'), _('Policy for creating new files')); 184 | o.editable = true; 185 | o.value('epall', _('Existing path - all')); 186 | o.value('epff', _('Existing path - first found')); 187 | o.value('eplfs', _('Existing path - least free space')); 188 | o.value('eplus', _('Existing path - least used space')); 189 | o.value('epmfs', _('Existing path - most free space')); 190 | o.value('eppfrd', _('Existing path - percentage free random distribution')); 191 | o.value('eprand', _('Existing path - random')); 192 | o.value('erofs', _('Read-only')); 193 | o.value('ff', _('First found')); 194 | o.value('lfs', _('Least free space')); 195 | o.value('lus', _('Least used space')); 196 | o.value('mfs', _('Most free space')); 197 | o.value('msplfs', _('Most shared path - least free space')); 198 | o.value('msplus', _('Most shared path - least used space')); 199 | o.value('mspmfs', _('Most shared path - most free space')); 200 | o.value('msppfrd', _('Most shared path - percentage free random distribution')); 201 | o.value('newest', _('Newest file')); 202 | o.value('pfrd', _('Percentage free random distribution')); 203 | o.value('rand', _('Random')); 204 | o.default = 'epmfs'; 205 | 206 | var parse_minfreespace = function(value) { 207 | if (!value || typeof value !== 'string') return ''; 208 | // 去除所有空格 209 | value = value.replace(/\s+/g, ''); 210 | // 转大写 211 | value = value.toUpperCase(); 212 | // 去除尾部B 213 | if (value.endsWith('B')) value = value.slice(0, -1); 214 | if (value == '') return value; 215 | // 保证有数字+单位,且单位为K/M/G之一 216 | var m = value.match(/^(\d+)([KMG])$/); 217 | if (m) { 218 | return m[1] + m[2]; 219 | } 220 | // 如果用户只输入了数字,默认加G 221 | m = value.match(/^(\d+)$/); 222 | if (m) { 223 | return m[1] + 'G'; 224 | } 225 | // 否则返回原值 226 | return value; 227 | }; 228 | 229 | // type: numberInput, name: minfreespace 230 | o = s.option(form.Value, 'minfreespace', _('Minimum free space')); 231 | o.placeholder = '4G'; 232 | o.editable = true; 233 | o.validate = function(section_id, value) { 234 | var parsed = parse_minfreespace(value); 235 | if (parsed == '' || /^\d+[KMG]$/.test(parsed)) { 236 | return true; 237 | } 238 | return _('Please enter a value like 4G, 500M, 100K'); 239 | }; 240 | o.cfgvalue = function(section_id) { 241 | var v = uci.get('mergerfs', section_id, 'minfreespace'); 242 | return parse_minfreespace(v); 243 | }; 244 | o.write = function(section_id, formvalue) { 245 | return uci.set('mergerfs', section_id, 'minfreespace', parse_minfreespace(formvalue)); 246 | }; 247 | 248 | // type: textInput, name: options 249 | o = s.option(form.Value, 'options', _('Options')); 250 | o.modalonly = true; 251 | o.placeholder = 'defaults,cache.files=off'; 252 | //o.default = 'defaults,cache.files=off'; 253 | 254 | return m.render(); 255 | } 256 | }); --------------------------------------------------------------------------------