Merge pull request #278 from nmav/ocserv
[project/luci.git] / modules / base / luasrc / ccache.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14 ]]--
15
16 local io = require "io"
17 local fs = require "nixio.fs"
18 local util = require "luci.util"
19 local nixio = require "nixio"
20 local debug = require "debug"
21 local string = require "string"
22 local package = require "package"
23
24 local type, loadfile = type, loadfile
25
26
27 module "luci.ccache"
28
29 function cache_ondemand(...)
30         if debug.getinfo(1, 'S').source ~= "=?" then
31                 cache_enable(...)
32         end
33 end
34
35 function cache_enable(cachepath, mode)
36         cachepath = cachepath or "/tmp/luci-modulecache"
37         mode = mode or "r--r--r--"
38
39         local loader = package.loaders[2]
40         local uid    = nixio.getuid()
41
42         if not fs.stat(cachepath) then
43                 fs.mkdir(cachepath)
44         end
45
46         local function _encode_filename(name)
47                 local encoded = ""
48                 for i=1, #name do
49                         encoded = encoded .. ("%2X" % string.byte(name, i))
50                 end
51                 return encoded
52         end
53
54         local function _load_sane(file)
55                 local stat = fs.stat(file)
56                 if stat and stat.uid == uid and stat.modestr == mode then
57                         return loadfile(file)
58                 end
59         end
60
61         local function _write_sane(file, func)
62                 if nixio.getuid() == uid then
63                         local fp = io.open(file, "w")
64                         if fp then
65                                 fp:write(util.get_bytecode(func))
66                                 fp:close()
67                                 fs.chmod(file, mode)
68                         end
69                 end
70         end
71
72         package.loaders[2] = function(mod)
73                 local encoded = cachepath .. "/" .. _encode_filename(mod)
74                 local modcons = _load_sane(encoded)
75                 
76                 if modcons then
77                         return modcons
78                 end
79
80                 -- No cachefile
81                 modcons = loader(mod)
82                 if type(modcons) == "function" then
83                         _write_sane(encoded, modcons)
84                 end
85                 return modcons
86         end
87 end