Go back to having all info in one rzdb file.
We can still split the rzdb file into a main file and a file data and a details file, but that's only for optimizing the required download size. On the system we always combine the parts back into one rzdb file once downloaded.
committer: J. Ali Harlow <ali@juiblex.co.uk>
2 * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
32 #include "razor-internal.h"
36 #define ARG_FLAG_OPT 0x1
37 #define ARG_FLAG_BYPASS 0x2
39 #define ARG(flags, swtch, index, type) \
40 ((flags) << 26 | (swtch) << 21 | \
42 #define ARG_FLAGS(arg) ((unsigned)(arg) >> 26)
43 #define ARG_SWTCH(arg) ((unsigned)(arg) >> 21 & 0x1F)
44 #define ARG_INDEX(arg) ((unsigned)(arg) >> 16 & 0x1F)
45 #define ARG_TYPE(arg) ((unsigned)(arg) & 0xFFFF)
48 #define ARG_STRING(n) ARG(0, 0, n, LUA_TSTRING)
49 #define ARG_OPT_STRING(n) ARG(ARG_FLAG_OPT, 0, n, LUA_TSTRING)
50 #define ARG_BYP_STRING(n, s) ARG(ARG_FLAG_BYPASS, s, n, LUA_TSTRING)
55 unsigned args[MAX_ARGS];
58 static struct razor_proxy proxy[] = {
59 { NULL, "dofile", LUA_TNONE, { ARG_STRING(1) } },
60 { NULL, "loadfile", LUA_TNONE, { ARG_OPT_STRING(1) } },
61 { "io", "input", LUA_TNONE, { ARG_OPT_STRING(1) } },
62 { "io", "output", LUA_TNONE, { ARG_OPT_STRING(1) } },
63 { "io", "lines", LUA_TNONE, { ARG_OPT_STRING(1) } },
64 { "io", "open", LUA_TNONE, { ARG_STRING(1) } },
65 { "io", "popen", LUA_TNONE, { ARG_STRING(1) } },
67 * Note: We do not proxy os.execute
68 * We can't do it properly (there is no way to distinguish filenames
69 * in arguments from any other strings) so it's better not to try.
70 * Scripts that attempt to be portable should use posix.exec[p]
72 { "os", "remove", LUA_TNONE, { ARG_STRING(1) } },
73 { "os", "rename", LUA_TNONE, { ARG_STRING(1), ARG_STRING(2) } },
75 * Note: We do not proxy os.tmpname
76 * It should never be used. scripts should use io.tmpfile instead
77 * if the rather limited functionality it provides suffices. The
78 * proper solution is to implement posix.mkstemp
80 { "posix", "access", LUA_TNONE, { ARG_STRING(1) } },
81 { "posix", "chdir", LUA_TNONE, { ARG_STRING(1) } },
82 { "posix", "chmod", LUA_TNONE, { ARG_STRING(1) } },
83 { "posix", "chown", LUA_TNONE, { ARG_STRING(1) } },
84 { "posix", "dir", LUA_TNONE, { ARG_OPT_STRING(1) } },
85 { "posix", "exec", LUA_TNONE, { ARG_STRING(1) } },
86 { "posix", "execp", LUA_TNONE, { ARG_STRING(1) } },
87 { "posix", "files", LUA_TNONE, { ARG_OPT_STRING(1) } },
88 { "posix", "getcwd", LUA_TSTRING, { ARG_NONE } },
89 { "posix", "glob", LUA_TTABLE, { ARG_STRING(1) } },
90 { "posix", "link", LUA_TNONE, { ARG_BYP_STRING(1, 3), ARG_STRING(2) } },
91 { "posix", "mkdir", LUA_TNONE, { ARG_STRING(1) } },
92 { "posix", "mkfifo", LUA_TNONE, { ARG_STRING(1) } },
93 { "posix", "pathconf", LUA_TNONE, { ARG_STRING(1) } },
94 { "posix", "readlink", LUA_TNONE, { ARG_STRING(1) } },
95 { "posix", "rmdir", LUA_TNONE, { ARG_STRING(1) } },
96 { "posix", "stat", LUA_TNONE, { ARG_STRING(1) } },
97 { "posix", "unlink", LUA_TNONE, { ARG_STRING(1) } },
98 { "posix", "utime", LUA_TNONE, { ARG_STRING(1) } },
101 static lua_CFunction execp_handler;
105 lua_CFunction handler[ARRAY_SIZE(proxy)];
108 static void *alloc_lua(void *user_data, void *ptr, size_t osize, size_t nsize)
114 return realloc(ptr, nsize);
117 static int proxy_execp(lua_State *L)
119 int r, n, err, got_eacces = 0;
120 char *file = strdup(luaL_checkstring(L, 1));
122 const char *s, *e, *path;
123 struct razor_lua *rl;
125 if (*file == '\0' || strchr(file, '/')) {
126 r = execp_handler(L);
131 (void)lua_getallocf(L, (void **)&rl);
133 path = getenv("PATH");
135 path = ":/bin:/usr/bin";
143 n = strlen(rl->root);
144 exe = malloc(n + (e - s) + 1 + strlen(file) + 1);
145 memcpy(exe, rl->root, n);
146 memcpy(exe + n, s, e - s);
149 strcpy(exe + n, file);
151 exe = malloc((e - s) + 1 + strlen(file) + 1);
152 memcpy(exe, s, e - s);
155 strcpy(exe + n, file);
157 /* Ensure exe contains a slash to avoid PATH search */
158 exe = malloc(2 + strlen(file) + 1);
161 strcpy(exe + 2, file);
163 lua_pushstring(L, exe);
167 r = execp_handler(L);
169 err = lua_tointeger(L, -1);
179 lua_pop(L, lua_gettop(L) - n);
196 lua_pushfstring(L, "%s: %s", file, strerror(err));
197 lua_pushinteger(L, err);
203 static int real2fake(lua_State *L, struct razor_lua *rl, int indx)
208 indx += lua_gettop(L) + 1;
210 if (lua_type(L, indx) == LUA_TSTRING) {
211 path = lua_tostring(L, indx);
212 if (path && !strncmp(path, rl->root, strlen(rl->root)) &&
213 (path[strlen(rl->root)] == '/' || !path[strlen(rl->root)])) {
214 lua_pushstring(L, path + strlen(rl->root));
215 lua_replace(L, indx);
223 static int proxy_handler(lua_State *L)
228 struct razor_lua *rl;
229 int method = lua_tointeger(L, lua_upvalueindex(1));
230 struct razor_proxy *rp = proxy + method;
232 (void)lua_getallocf(L, (void **)&rl);
234 for(i = 0; i < MAX_ARGS; i++) {
238 switch (ARG_TYPE(arg)) {
240 if (ARG_FLAGS(arg) & ARG_FLAG_BYPASS)
241 cond = !lua_toboolean(L, ARG_SWTCH(arg));
244 if (ARG_FLAGS(arg) & ARG_FLAG_OPT) {
245 if (lua_isstring(L, ARG_INDEX(arg)))
246 path = lua_tostring(L, ARG_INDEX(arg));
250 path = luaL_checkstring(L, ARG_INDEX(arg));
251 if (cond && path && *path == '/') {
252 lua_pushfstring(L, "%s%s", rl->root, path);
253 lua_replace(L, ARG_INDEX(arg));
257 lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
263 retval = rl->handler[method](L);
265 if (rp->result != LUA_TNONE && !lua_isnil(L, 1)) {
266 switch (rp->result) {
270 real2fake(L, rl, -1);
274 while (lua_next(L, -2)) {
275 if (real2fake(L, rl, -1)) {
276 i = lua_tonumber(L, -2);
277 lua_rawseti(L, -3, i);
283 lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
292 struct razor_lua_loader {
297 static struct razor_preload {
299 struct hashtable modules;
300 struct array name_pool;
301 struct array loaders;
302 } razor_preload = {0};
304 RAZOR_EXPORT void razor_set_lua_loader(const char *modname, void (*loader)())
307 struct razor_lua_loader *ploader, *end;
309 if (!razor_preload.init) {
310 razor_preload.init = 1;
311 array_init(&razor_preload.name_pool);
312 array_init(&razor_preload.loaders);
313 hashtable_init(&razor_preload.modules,
314 &razor_preload.name_pool);
317 name = hashtable_tokenize(&razor_preload.modules, modname);
319 end = razor_preload.loaders.data + razor_preload.loaders.size;
320 for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
321 if (ploader->name == name) {
322 ploader->func = loader;
326 ploader = array_add(&razor_preload.loaders, sizeof(*ploader));
327 ploader->name = name;
328 ploader->func = loader;
331 RAZOR_EXPORT void (*razor_get_lua_loader(const char *modname))()
334 struct razor_lua_loader *ploader, *end;
336 if (!razor_preload.init)
339 name = hashtable_lookup(&razor_preload.modules, modname);
341 end = razor_preload.loaders.data + razor_preload.loaders.size;
342 for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
343 if (ploader->name == name)
344 return ploader->func;
349 static void razor_lua_preload(lua_State *L)
351 struct razor_lua_loader *ploader, *end;
353 if (!razor_preload.init)
356 lua_getfield(L, LUA_GLOBALSINDEX, "package");
357 lua_getfield(L, -1, "preload");
360 end = razor_preload.loaders.data + razor_preload.loaders.size;
361 for(ploader = razor_preload.loaders.data; ploader < end; ploader++) {
362 lua_pushcfunction(L, ploader->func);
364 razor_preload.name_pool.data + ploader->name);
370 int run_lua_script(const char *root, const char *name, const char *body,
377 if (root && strcmp(root, "/"))
382 L = lua_newstate(alloc_lua, &rl);
384 razor_lua_preload(L);
385 lua_getglobal(L, "require");
386 lua_pushstring(L, "posix");
387 if (lua_pcall(L, 1, 1, 0)) {
388 fprintf(stderr, "lua posix: %s\n", lua_tostring(L, -1));
395 for(i = 0; i < ARRAY_SIZE(proxy); i++) {
396 if (proxy[i].table) {
397 lua_getglobal(L, proxy[i].table);
400 n = LUA_GLOBALSINDEX;
401 lua_getfield(L, n, proxy[i].name);
402 rl.handler[i] = lua_tocfunction(L, -1);
405 if (proxy[i].table &&
406 !strcmp(proxy[i].table, "posix") &&
407 !strcmp(proxy[i].name, "execp")) {
408 execp_handler = rl.handler[i];
409 rl.handler[i] = proxy_execp;
411 lua_pushinteger(L, i);
412 lua_pushcclosure(L, proxy_handler, 1);
413 lua_pushvalue(L, -2);
415 lua_setfield(L, n, proxy[i].name);
425 if (luaL_loadbuffer(L, body, len, name)) {
426 fprintf(stderr, "failed to load lua script\n");
431 if (lua_pcall(L, 0, 0, 0)) {
432 fprintf(stderr, "lua script failed: %s\n", lua_tostring(L, -1));