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