1 /*
2 * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
4 *
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
8 */
9 #include <lua.h>
10 #include <lauxlib.h>
11 #include <lualib.h>
12 #include "lua.h"
13
14 #include <l4/re/namespace>
15 #include <l4/re/util/cap_alloc>
16 #include <l4/re/util/unique_cap>
17 #include <l4/re/env>
18
19 #include "lua_cap.h"
20
21 #include <cstring>
22 #include <cstdio>
23
24 namespace Lua { namespace {
25
26 static int
__lookup(lua_State * l)27 __lookup(lua_State *l)
28 {
29 size_t len;
30 char const *s = lua_tolstring(l, lua_upvalueindex(2), &len);
31 Cap *_ns = Lua::check_cap(l, lua_upvalueindex(1));
32 L4_cap_fpage_rights rights
33 = (L4_cap_fpage_rights)lua_tointeger(l, lua_upvalueindex(3));
34
35 L4::Cap<L4Re::Namespace> ns(_ns->cap<L4Re::Namespace>().get());
36
37 auto obj = L4Re::Util::make_unique_cap<void>();
38 if (!obj.is_valid())
39 luaL_error(l, "out of caps");
40
41 lua_gc(l, LUA_GCCOLLECT, 0);
42
43 int r = ns->query(s, len, obj.get(), L4Re::Namespace::To_default);
44 #if 0
45 if (r == -L4_ENOENT)
46 return Cap::index(l);
47 #endif
48 if (r == -L4_ENOENT)
49 {
50 lua_pushnil(l);
51 return 1;
52 }
53
54 if (r < 0)
55 luaL_error(l, "runtime error %s (%d)\n", l4sys_errtostr(r), r);
56
57
58 Lua::Cap *no = Lua::push_void_cap(l);
59 no->set(obj.release());
60 no->set_rights(rights);
61
62 return 1;
63
64 }
65
66 static int
__query(lua_State * l)67 __query(lua_State *l)
68 {
69 //size_t len;
70 //char const *s = luaL_checklstring(l, 2, &len);
71 int argc = lua_gettop(l);
72 if (argc < 2)
73 luaL_error(l, "expected at least two arguments in name-space query");
74
75 lua_pushvalue(l, 1);
76 lua_pushvalue(l, 2);
77 if (argc > 2)
78 lua_pushvalue(l, 3);
79 else
80 lua_pushinteger(l, L4_FPAGE_RO);
81
82 lua_pushcclosure(l, __lookup, 3);
83 return 1;
84 }
85
86 static int
__register(lua_State * l)87 __register(lua_State *l)
88 {
89 Cap *ns = check_cap(l, 1);
90 char const *key = luaL_checkstring(l, 2);
91
92 Cap *n = 0;
93 lua_Integer type = lua_type(l, 3);
94 lua_gc(l, LUA_GCCOLLECT, 0);
95 switch (type)
96 {
97 case LUA_TNIL:
98 {
99 int r = ns->cap<L4Re::Namespace>()->unlink(key);
100 if (r >= 0 || r == -L4_ENOENT)
101 return 1;
102
103 luaL_error(l, "runtime error %s (%d)", l4sys_errtostr(r), r);
104 }
105 case LUA_TSTRING:
106 break;
107
108 case LUA_TUSERDATA:
109 n = Lua::check_cap(l, 3);
110 break;
111 default:
112 luaL_error(l, "unexpected value to register in namespace (%s)",
113 lua_typename(l, 3));
114 }
115
116 if (0)
117 printf("register %s=%lx in %lx\n",
118 key, n ? n->cap<void>().cap() : ~0UL, ns->cap<void>().cap());
119
120 int r;
121 L4::Cap<void> cap = n ? n->cap<void>().get() : L4::Cap<void>::Invalid;
122 unsigned rights = n ? n->rights() : L4_CAP_FPAGE_RO;
123 r = ns->cap<L4Re::Namespace>()
124 ->register_obj(key, L4::Ipc::make_cap(cap, rights),
125 L4Re::Namespace::Overwrite | rights);
126 if (r < 0)
127 luaL_error(l, "runtime error %s (%d)", l4sys_errtostr(r), r);
128
129 return 1;
130 }
131
132 struct Ns_model
133 {
134 static void
register_methodsLua::__anon0ef79ac40111::Ns_model135 register_methods(lua_State *l)
136 {
137 static const luaL_Reg l4_cap_class[] =
138 {
139 { "q", __query },
140 { "query", __query },
141 { "__register", __register },
142 { NULL, NULL }
143 };
144 luaL_setfuncs(l, l4_cap_class, 0);
145 Cap::add_class_metatable(l);
146 }
147 };
148
149
150 static Lua::Cap_type_lib<L4Re::Namespace, Ns_model> __lib;
151
152 }}
153
154