X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fsys%2Fluasrc%2Fsys.lua;h=f9b253e764c7063b52a72e91a1fa23c87087f33e;hp=9d03445bbbadd2a4b9c9e272623728fa7cc9ca81;hb=d60d892385735ef274278cf63d363917eb3e6361;hpb=07c0f405f3341cdfa11a8437c592fec5ff699f81 diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index 9d03445bb..f9b253e76 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -25,18 +25,19 @@ limitations under the License. ]]-- -local io = require "io" -local os = require "os" -local nixio = require "nixio" -local table = require "table" +local io = require "io" +local os = require "os" +local table = require "table" +local nixio = require "nixio" +local fs = require "nixio.fs" +local uci = require "luci.model.uci" local luci = {} luci.util = require "luci.util" -luci.fs = require "luci.fs" luci.ip = require "luci.ip" -local tonumber, ipairs, pairs, pcall, type, next = - tonumber, ipairs, pairs, pcall, type, next +local tonumber, ipairs, pairs, pcall, type, next, setmetatable, require = + tonumber, ipairs, pairs, pcall, type, next, setmetatable, require --- LuCI Linux and POSIX system utilities. @@ -58,20 +59,6 @@ end -- @return String containg the return the output of the command exec = luci.util.exec ---- Invoke the luci-flash executable to write an image to the flash memory. --- @param image Local path or URL to image file --- @param kpattern Pattern of files to keep over flash process --- @return Return value of os.execute() -function flash(image, kpattern) - local cmd = "luci-flash " - if kpattern then - cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' " - end - cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1" - - return os.execute(cmd) -end - --- Retrieve information about currently mounted file systems. -- @return Table containing mount information function mounts() @@ -135,7 +122,7 @@ getenv = nixio.getenv -- @return String containing the system hostname function hostname(newname) if type(newname) == "string" and #newname > 0 then - luci.fs.writefile( "/proc/sys/kernel/hostname", newname .. "\n" ) + fs.writefile( "/proc/sys/kernel/hostname", newname ) return newname else return nixio.uname().nodename @@ -179,28 +166,30 @@ end -- @return String containing the memory used for caching in kB -- @return String containing the memory used for buffering in kB -- @return String containing the free memory amount in kB +-- @return String containing the cpu bogomips (number) function sysinfo() - local cpuinfo = luci.fs.readfile("/proc/cpuinfo") - local meminfo = luci.fs.readfile("/proc/meminfo") + local cpuinfo = fs.readfile("/proc/cpuinfo") + local meminfo = fs.readfile("/proc/meminfo") - local system = cpuinfo:match("system typ.-:%s*([^\n]+)") - local model = "" local memtotal = tonumber(meminfo:match("MemTotal:%s*(%d+)")) local memcached = tonumber(meminfo:match("\nCached:%s*(%d+)")) local memfree = tonumber(meminfo:match("MemFree:%s*(%d+)")) local membuffers = tonumber(meminfo:match("Buffers:%s*(%d+)")) + local bogomips = tonumber(cpuinfo:match("[Bb]ogo[Mm][Ii][Pp][Ss].-: ([^\n]+)")) or 0 - if not system then - system = nixio.uname().machine - model = cpuinfo:match("model name.-:%s*([^\n]+)") - if not model then - model = cpuinfo:match("Processor.-:%s*([^\n]+)") - end - else - model = cpuinfo:match("cpu model.-:%s*([^\n]+)") - end + local system = + cpuinfo:match("system type\t+: ([^\n]+)") or + cpuinfo:match("Processor\t+: ([^\n]+)") or + cpuinfo:match("model name\t+: ([^\n]+)") - return system, model, memtotal, memcached, membuffers, memfree + local model = + cpuinfo:match("machine\t+: ([^\n]+)") or + cpuinfo:match("Hardware\t+: ([^\n]+)") or + luci.util.pcdata(fs.readfile("/proc/diag/model")) or + nixio.uname().machine or + system + + return system, model, memtotal, memcached, membuffers, memfree, bogomips end --- Retrieves the output of the "logread" command. @@ -219,7 +208,7 @@ end -- @param bytes Number of bytes for the unique id -- @return String containing hex encoded id function uniqueid(bytes) - local rand = luci.fs.readfile("/dev/urandom", bytes) + local rand = fs.readfile("/dev/urandom", bytes) return rand and nixio.bin.hexlify(rand) end @@ -247,36 +236,40 @@ end -- @return Table with the currently tracked IP connections function net.conntrack(callback) local connt = {} - if luci.fs.access("/proc/net/nf_conntrack", "r") then + if fs.access("/proc/net/nf_conntrack", "r") then for line in io.lines("/proc/net/nf_conntrack") do line = line:match "^(.-( [^ =]+=).-)%2" local entry, flags = _parse_mixed_record(line, " +") - entry.layer3 = flags[1] - entry.layer4 = flags[3] - for i=1, #entry do - entry[i] = nil - end + if flags[6] ~= "TIME_WAIT" then + entry.layer3 = flags[1] + entry.layer4 = flags[3] + for i=1, #entry do + entry[i] = nil + end - if callback then - callback(entry) - else - connt[#connt+1] = entry + if callback then + callback(entry) + else + connt[#connt+1] = entry + end end end - elseif luci.fs.access("/proc/net/ip_conntrack", "r") then + elseif fs.access("/proc/net/ip_conntrack", "r") then for line in io.lines("/proc/net/ip_conntrack") do line = line:match "^(.-( [^ =]+=).-)%2" local entry, flags = _parse_mixed_record(line, " +") - entry.layer3 = "ipv4" - entry.layer4 = flags[1] - for i=1, #entry do - entry[i] = nil - end + if flags[4] ~= "TIME_WAIT" then + entry.layer3 = "ipv4" + entry.layer4 = flags[1] + for i=1, #entry do + entry[i] = nil + end - if callback then - callback(entry) - else - connt[#connt+1] = entry + if callback then + callback(entry) + else + connt[#connt+1] = entry + end end end else @@ -313,11 +306,24 @@ function net.defaultroute6() local route net.routes6(function(rt) - if rt.dest:prefix() == 0 and (not route or route.metric > rt.metric) then + if rt.dest:prefix() == 0 and rt.device ~= "lo" and + (not route or route.metric > rt.metric) + then route = rt end end) + if not route then + local global_unicast = luci.ip.IPv6("2000::/3") + net.routes6(function(rt) + if rt.dest:equal(global_unicast) and + (not route or route.metric > rt.metric) + then + route = rt + end + end) + end + return route end @@ -369,13 +375,11 @@ end -- @return String containing the MAC address or nil if it cannot be found function net.ip4mac(ip) local mac = nil - - for i, l in ipairs(net.arptable()) do - if l["IP address"] == ip then - mac = l["HW address"] + net.arptable(function(e) + if e["IP address"] == ip then + mac = e["HW address"] end - end - + end) return mac end @@ -432,7 +436,7 @@ end -- { "source", "dest", "nexthop", "metric", "refcount", "usecount", -- "flags", "device" } function net.routes6(callback) - if luci.fs.access("/proc/net/ipv6_route", "r") then + if fs.access("/proc/net/ipv6_route", "r") then local routes = { } for line in io.lines("/proc/net/ipv6_route") do @@ -464,7 +468,11 @@ function net.routes6(callback) refcount = tonumber(refcnt, 16), usecount = tonumber(usecnt, 16), flags = tonumber(flags, 16), - device = dev + device = dev, + + -- lua number is too small for storing the metric + -- add a metric_raw field with the original content + metric_raw = metric } if callback then @@ -518,6 +526,9 @@ function process.list() end k = luci.util.split(luci.util.trim(line), "%s+", nil, true) + if k[6] == "%VSZ" then + k[6] = "%MEM" + end if k[1] == "PID" then break end @@ -581,14 +592,26 @@ user = {} -- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" } user.getuser = nixio.getpw +--- Retrieve the current user password hash. +-- @param username String containing the username to retrieve the password for +-- @return String containing the hash or nil if no password is set. +function user.getpasswd(username) + local pwe = nixio.getsp and nixio.getsp(username) or nixio.getpw(username) + local pwh = pwe and (pwe.pwdp or pwe.passwd) + if not pwh or #pwh < 1 or pwh == "!" or pwh == "x" then + return nil + else + return pwh + end +end + --- Test whether given string matches the password of a given system user. -- @param username String containing the Unix user name -- @param pass String containing the password to compare -- @return Boolean indicating wheather the passwords are equal function user.checkpasswd(username, pass) - local pwe = nixio.getsp and nixio.getsp(username) or nixio.getpw(username) - local pwh = pwe and (pwe.pwdp or pwe.passwd) - if not pwh or #pwh < 1 or pwh ~= "!" and nixio.crypt(pass, pwh) ~= pwh then + local pwh = user.getpasswd(username) + if pwh and nixio.crypt(pass, pwh) ~= pwh then return false else return true @@ -601,16 +624,17 @@ end -- @return Number containing 0 on success and >= 1 on error function user.setpasswd(username, password) if password then - password = password:gsub("'", "") + password = password:gsub("'", [['"'"']]) end if username then - username = username:gsub("'", "") + username = username:gsub("'", [['"'"']]) end - local cmd = "(echo '"..password.."';sleep 1;echo '"..password.."')|" - cmd = cmd .. "passwd '"..username.."' >/dev/null 2>&1" - return os.execute(cmd) + return os.execute( + "(echo '" .. password .. "'; sleep 1; echo '" .. password .. "') | " .. + "passwd '" .. username .. "' >/dev/null 2>&1" + ) end @@ -619,6 +643,52 @@ end -- @name luci.sys.wifi wifi = {} +--- Get wireless information for given interface. +-- @param ifname String containing the interface name +-- @return A wrapped iwinfo object instance +function wifi.getiwinfo(ifname) + local stat, iwinfo = pcall(require, "iwinfo") + + if ifname then + local c = 0 + local u = uci.cursor_state() + local d, n = ifname:match("^(%w+)%.network(%d+)") + if d and n then + n = tonumber(n) + u:foreach("wireless", "wifi-iface", + function(s) + if s.device == d then + c = c + 1 + if c == n then + ifname = s.ifname or s.device + return false + end + end + end) + elseif u:get("wireless", ifname) == "wifi-device" then + u:foreach("wireless", "wifi-iface", + function(s) + if s.device == ifname and s.ifname then + ifname = s.ifname + return false + end + end) + end + + local t = stat and iwinfo.type(ifname) + local x = t and iwinfo[t] or { } + return setmetatable({}, { + __index = function(t, k) + if k == "ifname" then + return ifname + elseif x[k] then + return x[k](ifname) + end + end + }) + end +end + --- Get iwconfig output for all wireless devices. -- @return Table of tables containing the iwconfing output for each wifi device function wifi.getiwconfig() @@ -673,27 +743,29 @@ end -- @param iface Wireless interface (optional) -- @return Table of available channels function wifi.channels(iface) - local cmd = "iwlist " .. ( iface or "" ) .. " freq 2>/dev/null" - local cns = { } - - local fd = io.popen(cmd) - if fd then - local ln, c, f - while true do - ln = fd:read("*l") - if not ln then break end - c, f = ln:match("Channel (%d+) : (%d+%.%d+) GHz") - if c and f then - cns[tonumber(c)] = tonumber(f) - end + local stat, iwinfo = pcall(require, "iwinfo") + local cns + + if stat then + local t = iwinfo.type(iface or "") + if iface and t and iwinfo[t] then + cns = iwinfo[t].freqlist(iface) end - fd:close() end - if not next(cns) then + if not cns or #cns == 0 then cns = { - 2.412, 2.417, 2.422, 2.427, 2.432, 2.437, - 2.442, 2.447, 2.452, 2.457, 2.462 + {channel = 1, mhz = 2412}, + {channel = 2, mhz = 2417}, + {channel = 3, mhz = 2422}, + {channel = 4, mhz = 2427}, + {channel = 5, mhz = 2432}, + {channel = 6, mhz = 2437}, + {channel = 7, mhz = 2442}, + {channel = 8, mhz = 2447}, + {channel = 9, mhz = 2452}, + {channel = 10, mhz = 2457}, + {channel = 11, mhz = 2462} } end @@ -711,8 +783,8 @@ init.dir = "/etc/init.d/" -- @return Table containing the names of all inistalled init scripts function init.names() local names = { } - for _, name in ipairs(luci.fs.glob(init.dir.."*")) do - names[#names+1] = luci.fs.basename(name) + for name in fs.glob(init.dir.."*") do + names[#names+1] = fs.basename(name) end return names end @@ -721,8 +793,8 @@ end -- @param name Name of the init script -- @return Boolean indicating whether init is enabled function init.enabled(name) - if luci.fs.access(init.dir..name) then - return ( call(init.dir..name.." enabled") == 0 ) + if fs.access(init.dir..name) then + return ( call(init.dir..name.." enabled >/dev/null") == 0 ) end return false end @@ -731,8 +803,8 @@ end -- @param name Name of the init script -- @return Numeric index value function init.index(name) - if luci.fs.access(init.dir..name) then - return call("source "..init.dir..name.."; exit $START") + if fs.access(init.dir..name) then + return call("source "..init.dir..name.." enabled >/dev/null; exit $START") end end @@ -740,8 +812,8 @@ end -- @param name Name of the init script -- @return Boolean indicating success function init.enable(name) - if luci.fs.access(init.dir..name) then - return ( call(init.dir..name.." enable") == 1 ) + if fs.access(init.dir..name) then + return ( call(init.dir..name.." enable >/dev/null") == 1 ) end end @@ -749,8 +821,8 @@ end -- @param name Name of the init script -- @return Boolean indicating success function init.disable(name) - if luci.fs.access(init.dir..name) then - return ( call(init.dir..name.." disable") == 0 ) + if fs.access(init.dir..name) then + return ( call(init.dir..name.." disable >/dev/null") == 0 ) end end