]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ned/server/src/lua_cap.cc
2ff492a362420f5e697dfd7e75229618c59075fe
[l4.git] / l4 / pkg / ned / server / src / lua_cap.cc
1 #include "lua.h"
2 #include "lua_cap.h"
3 #include "debug.h"
4
5
6 #include <l4/re/util/cap_alloc>
7 #include <l4/sys/types.h>
8 #include <l4/sys/meta>
9 #include <l4/cxx/ipc_stream>
10
11 namespace Lua {
12
13 void
14 get_cap_cast_table(lua_State *l)
15 {
16   lua_getglobal(l, package);
17   lua_getfield(l, -1, CAST_TABLE);
18   lua_remove(l, -2);
19 }
20
21 Cap::~Cap()
22 {
23 }
24
25 void
26 Cap::create_class(lua_State *l, Register_methods *rm, char const *type)
27 {
28   lua_newtable(l);
29   rm(l);
30   lua_pushstring(l, type);
31   lua_setfield(l, -2, "_CLASS_NAME");
32 }
33
34 void
35 Cap::get_class(lua_State *l)
36 {
37   get_cap_cast_table(l);
38   lua_getfield(l, -1, "void");
39   lua_remove(l, -2);
40 }
41
42 static int
43 is_valid(lua_State *l)
44 {
45   Cap *n = check_cap(l, 1);
46   lua_pushboolean(l, n && n->cap<void>().is_valid());
47   return 1;
48 }
49
50 static int
51 gc_cap(lua_State *l)
52 {
53   Lua::Cap *n = check_cap(l, 1);
54   n->~Cap();
55   return 1;
56 }
57
58
59 static int
60 tostring(lua_State *l)
61 {
62   Lua::Cap *n = check_cap(l, 1);
63   lua_getfenv(l, 1);
64   lua_rawgeti(l, -1, 0);
65   char const *type = "void";
66   if (!lua_isnil(l, -1))
67     {
68       lua_getfield(l, -1, "_CLASS_NAME");
69       type = lua_tostring(l, -1);
70     }
71
72   if (n->cap<void>().is_valid())
73     lua_pushfstring(l, "L4::Cap<%s>[%p] r=%p f=%p", type,
74                     (void*)(n->cap<void>().cap()),
75                     (void*)n->all_rights(), (void*)n->flags());
76   else
77     lua_pushfstring(l, "L4::Cap<%s>::Invalid", type);
78   return 1;
79 }
80
81 static Cap *
82 __set_rights(lua_State *l, unsigned r)
83 {
84   Lua::Cap *n = check_cap(l, 1);
85   if (n->all_rights() == r)
86     lua_pushvalue(l, 1);
87   else
88     {
89       Lua::Cap *t = n->clone(l);
90       t->set_rights(r);
91       lua_getfenv(l, 1);
92       lua_setfenv(l, -2);
93       return t;
94     }
95
96   return n;
97 }
98
99 static int
100 __set_mode_call(lua_State *l)
101 {
102   Cap *c;
103   if (lua_gettop(l) >= 2 && !lua_isnil(l, 2))
104     {
105       unsigned rights = L4_CAP_FPAGE_R;
106       if (lua_isnumber(l, 2))
107         rights = lua_tointeger(l, 2);
108       else
109         {
110           for (char const *r = lua_tostring(l, 2); *r; ++r)
111             {
112               switch (*r)
113                 {
114                 case 'r':
115                 case 'R': rights |= L4_CAP_FPAGE_R; break;
116                 case 'w':
117                 case 'W': rights |= L4_CAP_FPAGE_W; break;
118                 case 's':
119                 case 'S': rights |= L4_CAP_FPAGE_S; break;
120                 case 'd':
121                 case 'D': rights |= L4_CAP_FPAGE_D; break;
122                 case 'n':
123                 case 'N': rights |= 0x10; break;
124                 case 'c':
125                 case 'C': rights |= 0x20; break;
126                 }
127             }
128         }
129       c = __set_rights(l, rights);
130       return 1;
131     }
132   else
133     c = check_cap(l, 1);
134
135   lua_pushinteger(l, c->rights());
136
137   return 1;
138 }
139
140
141 static int
142 __full(lua_State *l)
143 {
144   __set_rights(l, 0xef);
145   return 1;
146 }
147
148
149 bool
150 Cap::find_dynamic_type(lua_State *l) const
151 {
152   using L4Re::Util::Ref_cap;
153   Dbg dbg(Dbg::Warn, "lua");
154   Ref_cap<L4::Meta>::Cap _meta = L4::cap_cast<L4::Meta>(_c);
155   L4::Ipc_istream res(l4_utcb());
156   res.tag() = _meta->interface(0);
157
158   if (int err = l4_error(res.tag()))
159     {
160       dbg.printf("Hm, cpapbility %lx does not support the meta protocol: %d\n",
161                  _c.cap(), err);
162       return false;
163     }
164
165   L4::Ipc::Varg name, proto;
166   res.get(&name);
167   res.get(&proto);
168
169   if (!name.is_of<char const *>())
170     return false;
171
172   if (!proto.is_of_int())
173     return false;
174
175   get_method_table(l, name.value<char const *>());
176   if (lua_isnil(l, -1))
177     { // no lua representation of type found
178       lua_pop(l, -1);
179       return false;
180     }
181
182   return true;
183 }
184
185 int
186 Cap::index(lua_State *l) const
187 {
188   get_method_table(l, "void"); // push table
189   lua_pushvalue(l, 2); // push key
190   lua_gettable(l, -2);
191
192   if (!lua_isnil(l, -1))
193     return 1;
194
195   lua_pop(l, 2); // pop nil result, and method table
196
197   lua_getfenv(l, 1);
198   lua_rawgeti(l, -1, 0);
199   if (lua_isnil(l, -1))
200     {
201       lua_pop(l, 1);
202       if (!find_dynamic_type(l))
203         return 0;
204
205       lua_pushvalue(l, -1); // keep table after set
206       lua_rawseti(l, -3, 0);
207     }
208
209   lua_pushvalue(l, 2); // push key
210   lua_gettable(l, -2);
211   return 1;
212 }
213
214 int
215 Cap::newindex(lua_State *) const
216 { return 0; }
217
218
219
220 static int __index(lua_State *l)
221 {
222   Lua::Cap *n = Lua::check_cap(l, 1);
223   return n->index(l);
224 }
225
226 static
227 void init_cap_metatable(lua_State *l)
228 {
229   Lua::register_method(l, "__gc", gc_cap);
230   Lua::register_method(l, "__tostring", tostring);
231   Lua::register_method(l, "__index", __index);
232 }
233
234 static
235 void push_cap_metatable(lua_State *l)
236 {
237   if (luaL_newmetatable(l, CAP_TYPE))
238     init_cap_metatable(l);
239 }
240
241 void set_cap_metatable(lua_State *l)
242 {
243   push_cap_metatable(l);
244   lua_setmetatable(l, -2);
245 }
246
247 int
248 Cap::get_method_table(lua_State *l, char const *typ) const
249 {
250   get_cap_cast_table(l);
251   lua_getfield(l, -1, typ /*type()*/);
252   lua_remove(l, -2);
253   return 1;
254 }
255
256 #if 0
257   if (luaL_newmetatable(l, type()))
258     {
259       luaL_register(l, NULL, l4_cap_class);
260       return 1;
261     }
262   return 0;
263 }
264 #endif
265
266 Cap *
267 push_void_cap(lua_State *l)
268 {
269   Cap *c = new (lua_newuserdata(l, sizeof(Cap))) Cap();
270   set_cap_metatable(l);
271   lua_newtable(l);
272   lua_setfenv(l, -2);
273   return c;
274 }
275
276
277 Cap *
278 push_new_cap(lua_State *l, bool void_cap)
279 {
280   int const frame = lua_gettop(l);
281   get_cap_cast_table(l);
282   lua_pushvalue(l, frame);
283   //long proto = lua_tointeger(l, frame);
284   lua_remove(l, frame);
285   lua_gettable(l, frame);
286   lua_remove(l, frame); // discard cast table
287
288   // and the type table or nil at index 'frame'
289
290   Cap *nc = 0;
291   bool found_type;
292   if ((found_type = !lua_isnil(l, frame)) || void_cap)
293     nc = push_void_cap(l); // cap at frame + 1
294
295   if (found_type)
296     {
297       lua_getfenv(l, frame + 1);
298       lua_pushvalue(l, frame);
299       lua_rawseti(l, -2, 0);
300       lua_pop(l, 1); // pop env table
301     }
302
303   lua_remove(l, frame); // cap or nothing at frame
304   return nc;
305 }
306
307 static int
308 __cast(lua_State *l)
309 {
310   if (lua_gettop(l) > 2)
311     luaL_error(l, "too man arguments to L4.cast (expected 2:type and cap)");
312
313   if (lua_isfunction(l, 2))
314     lua_call(l, 0, 1);
315
316   Cap *c = check_cap(l, 2);
317   lua_pushvalue(l, 1);
318   Cap *nc = push_new_cap(l, false);
319   if (nc)
320     {
321       nc->assign(c);
322       return 1;
323     }
324
325   lua_pushnil(l);
326   return 1;
327 }
328
329
330 void
331 init_lua_cap(lua_State *l)
332 {
333   static luaL_Reg _cast_f[] =
334   {
335     { "cast", __cast },
336     { NULL, NULL }
337   };
338   luaL_register(l, package, _cast_f);
339   lua_newtable(l);
340   lua_setfield(l, -2, CAST_TABLE);
341
342   get_cap_cast_table(l);
343   Cap::create_class(l, Cap::register_methods, "void");
344   lua_setfield(l, -2, "void");
345   lua_pop(l, 2);
346 }
347
348 void
349 Cap::register_methods(lua_State *l)
350 {
351   static const luaL_Reg l4_cap_class[] =
352   {
353     { "is_valid", is_valid },
354     { "svr",    __full },
355     { "rights", __set_mode_call },
356     { "mode",   __set_mode_call },
357     { "m",      __set_mode_call },
358     { NULL, NULL },
359   };
360   luaL_register(l, NULL, l4_cap_class);
361 }
362
363 }