summaryrefslogtreecommitdiffhomepage
path: root/libs/core/luasrc/ccache.lua
blob: 56ccbc3efe30a85bfb15544818ad0d49a0ad840f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
--[[
LuCI - Lua Configuration Interface

Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

$Id$
]]--

local io = require "io"
local fs = require "nixio.fs"
local util = require "luci.util"
local nixio = require "nixio"
local debug = require "debug"
local string = require "string"
local package = require "package"

local type, loadfile = type, loadfile


module "luci.ccache"

function cache_ondemand(...)
	if debug.getinfo(1, 'S').source ~= "=?" then
		cache_enable(...)
	end
end

function cache_enable(cachepath, mode)
	cachepath = cachepath or "/tmp/luci-modulecache"
	mode = mode or "r--r--r--"

	local loader = package.loaders[2]
	local uid    = nixio.getuid()

	if not fs.stat(cachepath) then
		fs.mkdir(cachepath)
	end

	local function _encode_filename(name)
		local encoded = ""
		for i=1, #name do
			encoded = encoded .. ("%2X" % string.byte(name, i))
		end
		return encoded
	end

	local function _load_sane(file)
		local stat = fs.stat(file)
		if stat and stat.uid == uid and stat.modestr == mode then
			return loadfile(file)
		end
	end

	local function _write_sane(file, func)
		if nixio.getuid() == uid then
			local fp = io.open(file, "w")
			if fp then
				fp:write(util.get_bytecode(func))
				fp:close()
				fs.chmod(file, mode)
			end
		end
	end

	package.loaders[2] = function(mod)
		local encoded = cachepath .. "/" .. _encode_filename(mod)
		local modcons = _load_sane(encoded)
		
		if modcons then
			return modcons
		end

		-- No cachefile
		modcons = loader(mod)
		if type(modcons) == "function" then
			_write_sane(encoded, modcons)
		end
		return modcons
	end
end