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