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