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