util.lua 17 KB

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