2
0

util.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local io = require "io"
  4. local math = require "math"
  5. local table = require "table"
  6. local debug = require "debug"
  7. local ldebug = require "luci.debug"
  8. local string = require "string"
  9. local coroutine = require "coroutine"
  10. local tparser = require "luci.template.parser"
  11. local json = require "luci.jsonc"
  12. local _ubus = require "ubus"
  13. local _ubus_connection = nil
  14. local getmetatable, setmetatable = getmetatable, setmetatable
  15. local rawget, rawset, unpack = rawget, rawset, unpack
  16. local tostring, type, assert, error = tostring, type, assert, error
  17. local ipairs, pairs, next, loadstring = ipairs, pairs, next, loadstring
  18. local require, pcall, xpcall = require, pcall, xpcall
  19. local collectgarbage, get_memory_limit = collectgarbage, get_memory_limit
  20. module "luci.util"
  21. --
  22. -- Pythonic string formatting extension
  23. --
  24. getmetatable("").__mod = function(a, b)
  25. local ok, res
  26. if not b then
  27. return a
  28. elseif type(b) == "table" then
  29. local k, _
  30. for k, _ in pairs(b) do if type(b[k]) == "userdata" then b[k] = tostring(b[k]) end end
  31. ok, res = pcall(a.format, a, unpack(b))
  32. if not ok then
  33. error(res, 2)
  34. end
  35. return res
  36. else
  37. if type(b) == "userdata" then b = tostring(b) end
  38. ok, res = pcall(a.format, a, b)
  39. if not ok then
  40. error(res, 2)
  41. end
  42. return res
  43. end
  44. end
  45. --
  46. -- Class helper routines
  47. --
  48. -- Instantiates a class
  49. local function _instantiate(class, ...)
  50. local inst = setmetatable({}, {__index = class})
  51. if inst.__init__ then
  52. inst:__init__(...)
  53. end
  54. return inst
  55. end
  56. -- The class object can be instantiated by calling itself.
  57. -- Any class functions or shared parameters can be attached to this object.
  58. -- Attaching a table to the class object makes this table shared between
  59. -- all instances of this class. For object parameters use the __init__ function.
  60. -- Classes can inherit member functions and values from a base class.
  61. -- Class can be instantiated by calling them. All parameters will be passed
  62. -- to the __init__ function of this class - if such a function exists.
  63. -- The __init__ function must be used to set any object parameters that are not shared
  64. -- with other objects of this class. Any return values will be ignored.
  65. function class(base)
  66. return setmetatable({}, {
  67. __call = _instantiate,
  68. __index = base
  69. })
  70. end
  71. function instanceof(object, class)
  72. local meta = getmetatable(object)
  73. while meta and meta.__index do
  74. if meta.__index == class then
  75. return true
  76. end
  77. meta = getmetatable(meta.__index)
  78. end
  79. return false
  80. end
  81. --
  82. -- Scope manipulation routines
  83. --
  84. local tl_meta = {
  85. __mode = "k",
  86. __index = function(self, key)
  87. local t = rawget(self, coxpt[coroutine.running()]
  88. or coroutine.running() or 0)
  89. return t and t[key]
  90. end,
  91. __newindex = function(self, key, value)
  92. local c = coxpt[coroutine.running()] or coroutine.running() or 0
  93. local r = rawget(self, c)
  94. if not r then
  95. rawset(self, c, { [key] = value })
  96. else
  97. r[key] = value
  98. end
  99. end
  100. }
  101. -- the current active coroutine. A thread local store is private a table object
  102. -- whose values can't be accessed from outside of the running coroutine.
  103. function threadlocal(tbl)
  104. return setmetatable(tbl or {}, tl_meta)
  105. end
  106. --
  107. -- Debugging routines
  108. --
  109. function perror(obj)
  110. return io.stderr:write(tostring(obj) .. "\n")
  111. end
  112. function dumptable(t, maxdepth, i, seen)
  113. i = i or 0
  114. seen = seen or setmetatable({}, {__mode="k"})
  115. for k,v in pairs(t) do
  116. perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
  117. if type(v) == "table" and (not maxdepth or i < maxdepth) then
  118. if not seen[v] then
  119. seen[v] = true
  120. dumptable(v, maxdepth, i+1, seen)
  121. else
  122. perror(string.rep("\t", i) .. "*** RECURSION ***")
  123. end
  124. end
  125. end
  126. end
  127. --
  128. -- String and data manipulation routines
  129. --
  130. function pcdata(value)
  131. return value and tparser.pcdata(tostring(value))
  132. end
  133. function striptags(value)
  134. return value and tparser.striptags(tostring(value))
  135. end
  136. -- for bash, ash and similar shells single-quoted strings are taken
  137. -- literally except for single quotes (which terminate the string)
  138. -- (and the exception noted below for dash (-) at the start of a
  139. -- command line parameter).
  140. function shellsqescape(value)
  141. local res
  142. res, _ = string.gsub(value, "'", "'\\''")
  143. return res
  144. end
  145. -- bash, ash and other similar shells interpret a dash (-) at the start
  146. -- of a command-line parameters as an option indicator regardless of
  147. -- whether it is inside a single-quoted string. It must be backlash
  148. -- escaped to resolve this. This requires in some funky special-case
  149. -- handling. It may actually be a property of the getopt function
  150. -- rather than the shell proper.
  151. function shellstartsqescape(value)
  152. res, _ = string.gsub(value, "^\-", "\\-")
  153. res, _ = string.gsub(res, "^-", "\-")
  154. return shellsqescape(value)
  155. end
  156. -- containing the resulting substrings. The optional max parameter specifies
  157. -- the number of bytes to process, regardless of the actual length of the given
  158. -- string. The optional last parameter, regex, specifies whether the separator
  159. -- sequence is interpreted as regular expression.
  160. -- pattern as regular expression (optional, default is false)
  161. function split(str, pat, max, regex)
  162. pat = pat or "\n"
  163. max = max or #str
  164. local t = {}
  165. local c = 1
  166. if #str == 0 then
  167. return {""}
  168. end
  169. if #pat == 0 then
  170. return nil
  171. end
  172. if max == 0 then
  173. return str
  174. end
  175. repeat
  176. local s, e = str:find(pat, c, not regex)
  177. max = max - 1
  178. if s and max < 0 then
  179. t[#t+1] = str:sub(c)
  180. else
  181. t[#t+1] = str:sub(c, s and s - 1)
  182. end
  183. c = e and e + 1 or #str + 1
  184. until not s or max < 0
  185. return t
  186. end
  187. function trim(str)
  188. return (str:gsub("^%s*(.-)%s*$", "%1"))
  189. end
  190. function cmatch(str, pat)
  191. local count = 0
  192. for _ in str:gmatch(pat) do count = count + 1 end
  193. return count
  194. end
  195. -- one token per invocation, the tokens are separated by whitespace. If the
  196. -- input value is a table, it is transformed into a string first. A nil value
  197. -- will result in a valid interator which aborts with the first invocation.
  198. function imatch(v)
  199. if type(v) == "table" then
  200. local k = nil
  201. return function()
  202. k = next(v, k)
  203. return v[k]
  204. end
  205. elseif type(v) == "number" or type(v) == "boolean" then
  206. local x = true
  207. return function()
  208. if x then
  209. x = false
  210. return tostring(v)
  211. end
  212. end
  213. elseif type(v) == "userdata" or type(v) == "string" then
  214. return tostring(v):gmatch("%S+")
  215. end
  216. return function() end
  217. end
  218. -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
  219. -- Recognized units are:
  220. -- o "y" - one year (60*60*24*366)
  221. -- o "m" - one month (60*60*24*31)
  222. -- o "w" - one week (60*60*24*7)
  223. -- o "d" - one day (60*60*24)
  224. -- o "h" - one hour (60*60)
  225. -- o "min" - one minute (60)
  226. -- o "kb" - one kilobyte (1024)
  227. -- o "mb" - one megabyte (1024*1024)
  228. -- o "gb" - one gigabyte (1024*1024*1024)
  229. -- o "kib" - one si kilobyte (1000)
  230. -- o "mib" - one si megabyte (1000*1000)
  231. -- o "gib" - one si gigabyte (1000*1000*1000)
  232. function parse_units(ustr)
  233. local val = 0
  234. -- unit map
  235. local map = {
  236. -- date stuff
  237. y = 60 * 60 * 24 * 366,
  238. m = 60 * 60 * 24 * 31,
  239. w = 60 * 60 * 24 * 7,
  240. d = 60 * 60 * 24,
  241. h = 60 * 60,
  242. min = 60,
  243. -- storage sizes
  244. kb = 1024,
  245. mb = 1024 * 1024,
  246. gb = 1024 * 1024 * 1024,
  247. -- storage sizes (si)
  248. kib = 1000,
  249. mib = 1000 * 1000,
  250. gib = 1000 * 1000 * 1000
  251. }
  252. -- parse input string
  253. for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
  254. local num = spec:gsub("[^0-9%.]+$","")
  255. local spn = spec:gsub("^[0-9%.]+", "")
  256. if map[spn] or map[spn:sub(1,1)] then
  257. val = val + num * ( map[spn] or map[spn:sub(1,1)] )
  258. else
  259. val = val + num
  260. end
  261. end
  262. return val
  263. end
  264. -- also register functions above in the central string class for convenience
  265. string.pcdata = pcdata
  266. string.striptags = striptags
  267. string.split = split
  268. string.trim = trim
  269. string.cmatch = cmatch
  270. string.parse_units = parse_units
  271. function append(src, ...)
  272. for i, a in ipairs({...}) do
  273. if type(a) == "table" then
  274. for j, v in ipairs(a) do
  275. src[#src+1] = v
  276. end
  277. else
  278. src[#src+1] = a
  279. end
  280. end
  281. return src
  282. end
  283. function combine(...)
  284. return append({}, ...)
  285. end
  286. function contains(table, value)
  287. for k, v in pairs(table) do
  288. if value == v then
  289. return k
  290. end
  291. end
  292. return false
  293. end
  294. -- Both table are - in fact - merged together.
  295. function update(t, updates)
  296. for k, v in pairs(updates) do
  297. t[k] = v
  298. end
  299. end
  300. function keys(t)
  301. local keys = { }
  302. if t then
  303. for k, _ in kspairs(t) do
  304. keys[#keys+1] = k
  305. end
  306. end
  307. return keys
  308. end
  309. function clone(object, deep)
  310. local copy = {}
  311. for k, v in pairs(object) do
  312. if deep and type(v) == "table" then
  313. v = clone(v, deep)
  314. end
  315. copy[k] = v
  316. end
  317. return setmetatable(copy, getmetatable(object))
  318. end
  319. function dtable()
  320. return setmetatable({}, { __index =
  321. function(tbl, key)
  322. return rawget(tbl, key)
  323. or rawget(rawset(tbl, key, dtable()), key)
  324. end
  325. })
  326. end
  327. -- Serialize the contents of a table value.
  328. function _serialize_table(t, seen)
  329. assert(not seen[t], "Recursion detected.")
  330. seen[t] = true
  331. local data = ""
  332. local idata = ""
  333. local ilen = 0
  334. for k, v in pairs(t) do
  335. if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
  336. k = serialize_data(k, seen)
  337. v = serialize_data(v, seen)
  338. data = data .. ( #data > 0 and ", " or "" ) ..
  339. '[' .. k .. '] = ' .. v
  340. elseif k > ilen then
  341. ilen = k
  342. end
  343. end
  344. for i = 1, ilen do
  345. local v = serialize_data(t[i], seen)
  346. idata = idata .. ( #idata > 0 and ", " or "" ) .. v
  347. end
  348. return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
  349. end
  350. -- with loadstring().
  351. function serialize_data(val, seen)
  352. seen = seen or setmetatable({}, {__mode="k"})
  353. if val == nil then
  354. return "nil"
  355. elseif type(val) == "number" then
  356. return val
  357. elseif type(val) == "string" then
  358. return "%q" % val
  359. elseif type(val) == "boolean" then
  360. return val and "true" or "false"
  361. elseif type(val) == "function" then
  362. return "loadstring(%q)" % get_bytecode(val)
  363. elseif type(val) == "table" then
  364. return "{ " .. _serialize_table(val, seen) .. " }"
  365. else
  366. return '"[unhandled data type:' .. type(val) .. ']"'
  367. end
  368. end
  369. function restore_data(str)
  370. return loadstring("return " .. str)()
  371. end
  372. --
  373. -- Byte code manipulation routines
  374. --
  375. -- will be stripped before it is returned.
  376. function get_bytecode(val)
  377. local code
  378. if type(val) == "function" then
  379. code = string.dump(val)
  380. else
  381. code = string.dump( loadstring( "return " .. serialize_data(val) ) )
  382. end
  383. return code -- and strip_bytecode(code)
  384. end
  385. -- numbers and debugging numbers will be discarded. Original version by
  386. -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
  387. function strip_bytecode(code)
  388. local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
  389. local subint
  390. if endian == 1 then
  391. subint = function(code, i, l)
  392. local val = 0
  393. for n = l, 1, -1 do
  394. val = val * 256 + code:byte(i + n - 1)
  395. end
  396. return val, i + l
  397. end
  398. else
  399. subint = function(code, i, l)
  400. local val = 0
  401. for n = 1, l, 1 do
  402. val = val * 256 + code:byte(i + n - 1)
  403. end
  404. return val, i + l
  405. end
  406. end
  407. local function strip_function(code)
  408. local count, offset = subint(code, 1, size)
  409. local stripped = { string.rep("\0", size) }
  410. local dirty = offset + count
  411. offset = offset + count + int * 2 + 4
  412. offset = offset + int + subint(code, offset, int) * ins
  413. count, offset = subint(code, offset, int)
  414. for n = 1, count do
  415. local t
  416. t, offset = subint(code, offset, 1)
  417. if t == 1 then
  418. offset = offset + 1
  419. elseif t == 4 then
  420. offset = offset + size + subint(code, offset, size)
  421. elseif t == 3 then
  422. offset = offset + num
  423. elseif t == 254 or t == 9 then
  424. offset = offset + lnum
  425. end
  426. end
  427. count, offset = subint(code, offset, int)
  428. stripped[#stripped+1] = code:sub(dirty, offset - 1)
  429. for n = 1, count do
  430. local proto, off = strip_function(code:sub(offset, -1))
  431. stripped[#stripped+1] = proto
  432. offset = offset + off - 1
  433. end
  434. offset = offset + subint(code, offset, int) * int + int
  435. count, offset = subint(code, offset, int)
  436. for n = 1, count do
  437. offset = offset + subint(code, offset, size) + size + int * 2
  438. end
  439. count, offset = subint(code, offset, int)
  440. for n = 1, count do
  441. offset = offset + subint(code, offset, size) + size
  442. end
  443. stripped[#stripped+1] = string.rep("\0", int * 3)
  444. return table.concat(stripped), offset
  445. end
  446. return code:sub(1,12) .. strip_function(code:sub(13,-1))
  447. end
  448. --
  449. -- Sorting iterator functions
  450. --
  451. function _sortiter( t, f )
  452. local keys = { }
  453. local k, v
  454. for k, v in pairs(t) do
  455. keys[#keys+1] = k
  456. end
  457. local _pos = 0
  458. table.sort( keys, f )
  459. return function()
  460. _pos = _pos + 1
  461. if _pos <= #keys then
  462. return keys[_pos], t[keys[_pos]], _pos
  463. end
  464. end
  465. end
  466. -- the provided callback function.
  467. function spairs(t,f)
  468. return _sortiter( t, f )
  469. end
  470. -- The table pairs are sorted by key.
  471. function kspairs(t)
  472. return _sortiter( t )
  473. end
  474. -- The table pairs are sorted by value.
  475. function vspairs(t)
  476. return _sortiter( t, function (a,b) return t[a] < t[b] end )
  477. end
  478. --
  479. -- System utility functions
  480. --
  481. function bigendian()
  482. return string.byte(string.dump(function() end), 7) == 0
  483. end
  484. function exec(command)
  485. local pp = io.popen(command)
  486. local data = pp:read("*a")
  487. pp:close()
  488. return data
  489. end
  490. function execi(command)
  491. local pp = io.popen(command)
  492. return pp and function()
  493. local line = pp:read()
  494. if not line then
  495. pp:close()
  496. end
  497. return line
  498. end
  499. end
  500. -- Deprecated
  501. function execl(command)
  502. local pp = io.popen(command)
  503. local line = ""
  504. local data = {}
  505. while true do
  506. line = pp:read()
  507. if (line == nil) then break end
  508. data[#data+1] = line
  509. end
  510. pp:close()
  511. return data
  512. end
  513. function ubus(object, method, data)
  514. if not _ubus_connection then
  515. _ubus_connection = _ubus.connect()
  516. assert(_ubus_connection, "Unable to establish ubus connection")
  517. end
  518. if object and method then
  519. if type(data) ~= "table" then
  520. data = { }
  521. end
  522. return _ubus_connection:call(object, method, data)
  523. elseif object then
  524. return _ubus_connection:signatures(object)
  525. else
  526. return _ubus_connection:objects()
  527. end
  528. end
  529. function serialize_json(x, cb)
  530. local js = json.stringify(x)
  531. if type(cb) == "function" then
  532. cb(js)
  533. else
  534. return js
  535. end
  536. end
  537. function libpath()
  538. return require "nixio.fs".dirname(ldebug.__file__)
  539. end
  540. function checklib(fullpathexe, wantedlib)
  541. local fs = require "nixio.fs"
  542. local haveldd = fs.access('/usr/bin/ldd')
  543. if not haveldd then
  544. return false
  545. end
  546. local libs = exec("/usr/bin/ldd " .. fullpathexe)
  547. if not libs then
  548. return false
  549. end
  550. for k, v in ipairs(split(libs)) do
  551. if v:find(wantedlib) then
  552. return true
  553. end
  554. end
  555. return false
  556. end
  557. --
  558. -- Coroutine safe xpcall and pcall versions modified for Luci
  559. -- original version:
  560. -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
  561. --
  562. -- Copyright © 2005 Kepler Project.
  563. -- Permission is hereby granted, free of charge, to any person obtaining a
  564. -- copy of this software and associated documentation files (the "Software"),
  565. -- to deal in the Software without restriction, including without limitation
  566. -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
  567. -- and/or sell copies of the Software, and to permit persons to whom the
  568. -- Software is furnished to do so, subject to the following conditions:
  569. --
  570. -- The above copyright notice and this permission notice shall be
  571. -- included in all copies or substantial portions of the Software.
  572. --
  573. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  574. -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  575. -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  576. -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  577. -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  578. -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  579. -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  580. local performResume, handleReturnValue
  581. local oldpcall, oldxpcall = pcall, xpcall
  582. coxpt = {}
  583. setmetatable(coxpt, {__mode = "kv"})
  584. -- Identity function for copcall
  585. local function copcall_id(trace, ...)
  586. return ...
  587. end
  588. -- values of either the function or the error handler
  589. function coxpcall(f, err, ...)
  590. local res, co = oldpcall(coroutine.create, f)
  591. if not res then
  592. local params = {...}
  593. local newf = function() return f(unpack(params)) end
  594. co = coroutine.create(newf)
  595. end
  596. local c = coroutine.running()
  597. coxpt[co] = coxpt[c] or c or 0
  598. return performResume(err, co, ...)
  599. end
  600. -- values of the function or the error object
  601. function copcall(f, ...)
  602. return coxpcall(f, copcall_id, ...)
  603. end
  604. -- Handle return value of protected call
  605. function handleReturnValue(err, co, status, ...)
  606. if not status then
  607. return false, err(debug.traceback(co, (...)), ...)
  608. end
  609. if coroutine.status(co) ~= 'suspended' then
  610. return true, ...
  611. end
  612. return performResume(err, co, coroutine.yield(...))
  613. end
  614. -- Resume execution of protected function call
  615. function performResume(err, co, ...)
  616. return handleReturnValue(err, co, coroutine.resume(co, ...))
  617. end